1.全局变量
①全局变量的定义与性质
定义在函数外面的变量是全局变量,全局变量具有全局的生存期和作用域,它们与任何函数都无关,在任何函数内部都可以使用它们。
例1:全局变量
#include<stdio.h>
int f(void);
int g=12; //定义全局变量
int main(int argc, char const *argv[])
{
printf("g=%d\n",g);
f(); //函数调用
printf("g=%d\n",g);
return 0;
}
int f(void)
{
g+=2;
printf("g=%d\n",g);
return g;
}
运行结果
②全局变量初始化
如果没有做初始化,全局变量会得到0值,这点与本地变量不同;
如果是指针的话会得到NULL值;
只能用编译时刻已知的值来初始化全局变量(int g1=12; int g2=g1; 这种定义是错误的);
它们的初始化发生在main函数之前。
③被隐藏的全局变量
如果在函数内部存在与全局变量同名的变量,全局变量会被隐藏。
也就是说在更小的范围内定义了一个同名的变量,则全局变量就会被隐藏。
④静态本地变量
在本地变量定义时加上static修饰符就成为静态本地变量;当函数离开的时候,静态本地变量会继续存在并保持其值;静态本地变量的初始化只会在第一次进入这个函数时做,以后进入函数时会保持上次离开时候的值。
静态本地变量实际上是特殊的全局变量,它们位于相同的内存区域。
静态本地变量具有全局的生存期,函数内的局部作用域,static在这里的意思是局部作用域(本地可访问)。
例2:静态本地变量
int f(void);
int main(int argc, char const *argv[])
{
f();
f();
f();
return 0;
}
int f(void)
{
int all = 1;
printf("all=%d\n",all);
all +=2;
printf("agn all=%d\n",all);
return all;
}
这里的all是一般的本地变量,程序运行结果为:
如果对上面程序进行修改,将all改成静态本地变量,语句如下:
static int all = 1;
程序运行结果为:
2. 编译预处理和宏
①编译预处理指令
#开头的是编译预处理指令,它们不是C语言的成分,但是C语言程序离不开它。
#define用来定义一个宏。
例3:宏
#include<stdio.h>
#define PI 3.14159
int main(int argc, char const *argv[])
{
printf("%f\n",PI);
return 0;
}
②宏定义
#define <名字> <值>
注意没有结尾的分号,因为它不是C语言的语句,名字必须是一个单词,值可以是各种东西。
在C语言的编译器开始编译之前,编译预处理程序会将程序中的名字换成值,是完全的文本替换。
③宏的性质
如果一个宏的值中有其他的宏的名字,也是会被替换的;
如果一个宏的值超过一行,最后一行之前的行末要加“\”;
宏的值后面出现的注释不会被当做宏的值的一部分。
#define PI 3.14159
#define PI2 2*PI //2*PI
#define PRT printf(”%f”,PI);\
printf(“%f\n”,PI2)
上面的PI2中的PI会被替换,注释的内容不影响程序,但是如果直接用空格是不可以的。
④预定义的宏
LINE 表示源代码当前位置的行号
FILE 表示文件名
DATE 表示编译时候的日期
TIME 表示编译时候的时间
STDC
printf("%s:%d\n",FILE,LINE);
printf("%s:%d\n",DATE,TIME)
⑤带参数的宏
例4:像函数的宏
#include<stdio.h>
#define cube(x)((x)*(x)*(x))
int main(int argc, char const *argv[])
{
int i=5;
printf("%d\n",cube(i)); //((i)*(i)*(i))
return 0;
}
错误定义的宏:
#define G1(x) (x*57.22)
#define G2(x) (x)*57.22
G1I(5+2)会变成5+257.22而不是(5+2)57.22
100/G2(1)会变成100/157.22而不是100/(157.22)
所以我们写带参数的宏的时候一定要记得加括号,最外面要加括号,参数也要加括号。
带参数的宏矿业带多个参数:
#define MIN(a,b)((a)>(b)?(b):(a))
另外,带参数的宏也可以嵌套使用。