【知识点学习】

9.25

1.头文件

把函数原型放头文件里,在需要调用这个函数的源代码文件(.c)文件里#include这个头文件,就能编译时知道它是原型,来决定函数定义是否符合该头文件,如:(要用就include max.h)

  • #include 预处理指令 和宏一样 编译前被处理
  • 把文件全部文本内容原封不动插入所在地 so也不一定要在.c文件最前面#include
  • include 就是把头文件所在的里头的文本插入include所在的那行

#include两种形式指出要插入的文件
“”:要求编译器首先在当前.c文件所在目录找,若没有则到指定编译器目录找
<>:让编译器只在指定目录找
编译器自己懂自己的标准库的头文件在哪
环境变量和编译器命令行参数也可以指定寻找头文件目录

在使用 定义这个函数的地方都应该#include这个头文件
一般就是任何.c都有对应的同名.h 把所有对外公开的函数原型和全局变量(可在多个.c文件中共享 但要用恰当方式告诉别人该全局变量原型是什么 )的声明都放进去

误区
#include 不是用来引入库的 stdio.h里只有printf的原型 printf的代码在另外地方
现在C编译器默认会引入所有标准库

不对外公开的函数
在函数前加static就使得它成为只能在所在的编译单元中被使用的函数
在全局变量前加上static就使得它成为只能在所在的编译单元(.c文件)中被使用的全局变量

2.声明

int i;是变量的定义
exturn int i;是变量的声明
exturn=继承(相当于)

声明和定义:

声明可以多次 定义只能一次

  • 声明不产生代码 定义产生代码

头文件

  • 只有声明可被放在头文件中,是规则不是法律 否则会造成一个项目中多个编译单元里有重名的实体
  • *某些编译器允许几个编译单元中存在同名函数 / 用week修饰符强调这种存在(week修饰符:指定日期属于一年中的哪一周)
  • 同一编译单元里同名结构不可被重复声明,如果头文件里有结构声明,该头文件容易在一个编译单元里被#include多次,so需要“标准头文件结构”
标准头文件结构:
  • 用条件编译和宏,保证该文件在一个编译单元中只会被#include一次 #pragma once 也能起到相同作用,但也不是所有编译器都支持

3.格式化输入和输出:

printf(“%9d\n”, 123); 输出: 123(六个空格123) 9意为输出要占据9个字符的空间
printf(“%-9d\n”, 123); 输出:123(前无空格) -意为左对齐
printf(“%09d\n”,123); 输出:000000123(填充6个0) 0意为用0填充123前面的空位

scanf中 :%d只能读十进制的整数;%i据输入的整数的情况决定到底以哪种形式读进
0–>八进制; x–>十六进制
scanf返回值告诉我们该次读了几个item、变量;
printf返回值告诉我们这次输出了几个字符

类型修饰:

1️⃣整数:hh --> 单字节;
2️⃣h --> short;
3️⃣l --> long;
4️⃣II --> longlong;
5️⃣L --> logdouble.

4.文件的输入和输出

  • 用>和<做重定向

打开文件的标准代码:

FILE* fp = fopen("file", "r");
if (fp)
{
	fcanf(fp...);
	fclose(fp);

}
else
{
	...
}

fopen:
r --> 打开只读;
r+ --> 打开读写,从文件头开始读写,一般来修改;
w --> 打开只读,如不存在则新建,如存在则清空;
w+ --> 打开读写,如不存在则新建,如存在则清空;
a --> 打开追加,如不存在则新建,如存在则从文件尾开始;
··x --> 只新建,如文件已存在则不能打开。

5.二进制文件

其实所有文件最终都是二进制
文本文件无非是用最简单的方式可以读写的文件

  • more,tail
  • cat
  • vi
    二进制文件需要专门程序读写,文本文件的输入输出是格式化 可能经过转码
    在这里插入图片描述

6.类型定义

自定义数据类型(typedef)

typedef int length(成为int类型的别名 代替int出现在变量定义和参数声明的地方)
1.Length a,b,len; =int { … }
Length numbers[ 10 ];
=int{ … }

Typedef(声明新类型名)

  • 新名字是某类型别名
  • 改善程序可读性
    Typedef +原类型 新名字
    如:
typedef struct node aNode
{
  int data;
}aNode;
或
typedef struct aNode(用aNode 代替struct node)

7.联合:

大小端储存, x86(小端机器);
低位在前(低位放在低地址前),反之。

全局变量:
  • 定义在函数外部的变量,有全局生存期、作用域;
  • 与任何函数无关,在任何函数内部都可以使用它们
本地变量:
  • 进该函数时才出现,离开则不存在(但都在函数内部)

全变初始化(发生在main前)

  • 没做初始化会得到0值(全变)
  • 而指针会得到NULL值
  • 只能用编译时刻已知值来初始化全局变量

被隐藏的全局变量
函数内部存在一个与全局变量同名的变量,则全变会被隐藏

静态本地变量(有全局的生存期 函数内的局部作用 / 本地作用域):特殊全局变量 位于相同内存区域
  • 本地变量定义时+static 演示符 就成静态本地变量(函数离开–> 静态本地变量会继续存在并保持其值)
  • 初始化:第一次进入函数是做,以后进都保持上次离开的值
    static在这意为局部作用域(本地可访问)
全局变量小贴士

*返回指针的函数

  • 返回本地变量地址危险,返回全局变量 / 静态本地变量安全
  • 返回在函数内malloc的内存安全,但容易造成问题
  • best:返回传入的指针

tips:
1.不用全局变量在函数间传递参数和结果
2.尽量避免全局变量
3.*使用全局变量和静态本地变量的函数是多线程不安全的

8.宏

一.定义

#:编译预处理指令(不是C语言的成分,但是C语言离不开它们)
#define 来定义一个宏 <名字> <值>
因为不是C的语句,so结尾没有分号
C在开始编译前,预处理程序(把程序中的程序换成值)
一个宏有其他的名,也会被替换
if一个宏的值超过一行,则最后之前的行末要加\(反斜杠)
宏的值后面出现的注释不会被当作是宏的值的一部分
多行定义宏最好放在一起

二.没有值的宏(如:#define _DEBUG)
  • 用于条件编译,后面还有其他编译预处理指令检查该宏是否被定义过

预定义宏:(前后带两下划线)
__ LINE __(代码文件所在行号)
__ FILE __(文件名)
__ DATE __(编译时的日期)
__ TIME __(编译时的时间)
__ STDC __

带参数的宏


像函数的宏:

  • #define cube(x)((x)* (x)**(x)***) 【都只有一个 *】

  • 宏可带参数
    (一切都要括号!整个值要括号 参数出现的每个地方都要括号)
    #define RADTODEG((x)(x)*57.29578)【不加分号】
    可带多个参数,也可以组合嵌套使用别的宏

  • 大程序中普遍 可以复杂,比如:“产生函数”; 在#和##下,,存在中西文化差异 部分会被inline函数代替,无检查类型不好检查bug

  • main()中代码太长,适合分成几个函数

  • 一个源代码文件太长可分为几个文件

  • 两独立源代码文件不能编译成可执行文件

项目

  • 新建项,把几个源代码文件加入,编译会把一个项目的所有源代码文件都编译后链接起来

9.字符数组

char
字符串:
1️⃣以0结尾的一串字符,0/ '\0’是一样的;
2️⃣0是表示字符串结束,但不是字符串的一部分;
3️⃣计算字符串长度时不包含0;
4️⃣字符串以数组形式存在,以数组或指针形式访问(更多以指针形式)。

string.h里有很多处理字符串的函数

字符串变量,编译器会替你生成一个结尾表示结束(即长度为肉眼可见的1)

要把字符串写成什么形式?

数组:这个字符串在这里(作为本地变量空间会自动被回收)
指针:字符串不知道在哪里(作处理参数,动态分配空间)

常见错误:以为char*是字符串类型,定义了一个字符串类型的变量string就可以直接使用(✖);
由于没对string初始化为0,so不一定每次运行都出错
空字符串还是有效的“ ”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值