1.全局变量
定义在函数外部的变量叫做全局变量
全局变量具有全局的生存周期,作用域从声明他开始到末尾
没有初始化的全局变量会得到0值,指针会得到NULL值(本地变量不会给初值,保存的是内存中原有的值)
全局变量的初始化只能用编译时已知的值来初始化(只有常数,和常量const(不建议) 可以用来给它赋值)
如果函数内部存在和全局变量同名的本地变量,全局变量会被隐藏
2.静态本地变量 static 关键字
用static修饰的本地变量是静态本地变量(也可以修饰全局变量,加了之后表示只能在该c文件中使用,同一个项目下的其他c文件不能共享)
当函数执行结束离开时,函数内部的静态本地变量会继续保持其值
静态本地变量的初始化只会在第一次进入这个函数的时候做,以后进入这个函数的时候会保持上次离开的值
void fun(){
static int x=10; //只做一次
x++; //每次调用都执行,因此调用n次之后x值时10+n而不是11
}
静态本地变量的本质是全局变量,它和全局变量保存在相同的内存区域中,static关键字实质只是限制这个全局变量的范围为这个函数内
3.返回指针的函数
返回本地变量的指针是危险的,因为一旦函数结束,这块地址就相当于回收了,这个地址可能之后会被分配给其他变量
返回全局、静态本地变量、malloc的地址是安全的,最好的做法是返回传入的指针
4.使用全局变量tips
不要使用全局变量来在函数间传递参数或者作为返回结果
尽量避免使用全局变量
全局变量和静态本地变量对于多线程的环境是不安全的
5.编译预处理指令和宏
#开头的是编译预处理指令,他们不是C语言的部分,但是C语言离不开他们
#define 用来定义一个宏(c99以前没有const,只能用define来定义常量)
例:#define PI 3.1415 在编译器预处理的时候,会把程序中所有的PI换成3.1415
编译预处理
.c->.i->.s->.o->可执行文件
其中.c是源文件,.i是编译预处理后的文件,.s是汇编程序,.o是目标文件
可以用宏来定义宏
例如:#define PI2 2*PI
一行宏的定义没结束可以在末尾加一个反斜杠
除了可以定义有值的宏,还可以定义没有值的宏,这类宏是用于条件编译的
预定义宏:
_LINE_ 源代码当前的行号
_FILE_ 源代码文件的文件名
_DATE_ 编译时候的日期
_TIME_ 编译时候的时间
6.带参数的宏
像函数一样的宏
例如 #define cube(x) x*x*x
之后在程序中 cube(5) 会表示5*5*5
错误定义的宏
#define RADTODEG(x) (x*57.29578) //printf("%f ",RADTODEG(5+2))表示printf("%f ",(5+2*57.29578) //从而导致2先乘以57.29578
#define RADTODEG(x) (x)*57.29578 //printf("%f ",180/RADTODEG(1))表示printf("%f ",180/(1)*57.29578) //导致180先/1
带参数宏的原则:一切都要有括号
a.整个值要有括号
b.参数出现的每个地方都要有括号
#define RADTODEG(x) ((x)*57.29578) //正确
宏可以带多个参数
#define MIN(a,b) ((a)>(b)?(b):(a))
宏可以嵌套组合使用其他宏
宏后面不要加分号
带参数的宏在大型程序代码中使用非常普遍,可以非常复杂,例如产生函数
7.大程序结构
main函数里面内容太多可以写到新的函数里面
源文件太大可以分为多个源文件,但是需要解决多个源文件不能编译成可执行文件的问题
解决方案:在dev-c++中新建一个项目,然后将这多个源文件加入进去,dev-c++会将所有源文件编译之后链接起来(有的IDE会先分开编译,再对整个项目做链接)
8.头文件
把函数原型放到头文件(以.h结尾的文件)中,在需要调用这个函数的源代码文件(.c文件)中#include这个头文件,就能让编译器在编译的时候知道函数原型
在自定义函数的源文件中也要#include这个函数的头文件
#include是一个编译预处理指令,在编译之前就处理了,它将会把被include的的文件的全部内容原封不动的插入到它所在的地方
9.两种#include
#include"" 要求编译器首先在当前.c文件所在目录下寻找这个文件,如果没有,就到编译器指定目录中去寻找
#include<>让编译器只在指定目录去找
编译器自己知道自己的标准库的头文件在哪(windows下一边在ide的某个include目录下)
注意:#include 不是用来引入库的,真正的函数原型可能在某个.lib文件中,#include只是为了让编译器知道printf函数的原型,保证调用时参数类型匹配
10.变量的声明
在头文件中 :extern 变量类型 变量名 //声明一个变量,这个变量可以在这个项目下的所有.c文件中使用,前提是.c文件中有#include这个.h文件
注意声明的时候是不能初始化的
在C中,声明是不会产生代码的东西,具体有
函数原型
变量声明
结构声明
宏声明
枚举声明
类型声明
inline函数
而定义是会产生代码的东西
.h中声明常常用到一下东西,称为标准头文件结构
#ifndef _MAX_H_ //_MAX_H_ 表示max.h头文件 #define _MAX_H_ #endif
避免调用重复的声明从而产生的编译错误