全局变量和宏

全局变量

即定义在所有函数之外(一般都定义在main函数之前,#include头文件下边)的变量,这个是与局部变量(本地变量)所不同的,它可以在任何函数中使用

下面举个例子

1

# include <stdio.h>

int i;
int * p;

int main(void) {
	
	printf("全局变量 i 的值为%d\n", i);
	printf("全局变量 p 的值为%s\n", p);
	
	return 0; 
}

输出结果为:

 

没有初始化的全局变量会被赋予0这个值,如果是指针,会被赋予NULL这点通过上面程序的结果即可发现;对全局变量进行初始化时,最好直接用编译时刻已知的值(即数字或常变量等),但最好只是用数字而不要使用其他方法

它的初始化发生在main函数之前

如果在函数内部有变量与全局变量名相同,则在该函数中,全局变量会被覆盖

2

# include <stdio.h>

int i;
//int * p;
void f();

int main(void) {
	i = 9;
	
	printf("在%s函数中 i 的值为%d\n", __func__, i);
//	printf("全局变量 p 的值为%s\n", p);
	f();
	
	return 0; 
}

void f() {
	int i = 3;
	printf("在%s函数中 i 的值为%d\n", __func__, i);
}

输出结果为:

 

由上结果可以证明

另外,通过上面的例子可以发现,printf中放一个 %s ,而再输出的后面,对应的加一个__func__,则会输出该语句所在的函数的名字


上面的例子是在局部函数中定义相同变量名,覆盖了全局变量,下面举个全局变量的使用范围例子


3

# include <stdio.h>

int i;
//int * p;
void k(); 
void f();

int main(void) {
	i = 9;
	
	printf("在%s函数中 i 的值为%d\n", __func__, i);
//	printf("全局变量 p 的值为%s\n", p);
	f();
	printf("在%s函数中 i 的值为%d\n", __func__, i);
	
	return 0; 
}

void f() {
//	int i = 3;
	printf("在%s函数中 i 的值为%d\n", __func__, i);
	k();
	printf("在%s函数中 i 的值为%d\n", __func__, i);
}

void k() {
	i = 1000;
	printf("在%s函数中 i 的值为%d\n", __func__, i);
}

输出结果为:

 

静态局部变量

就是在定义局部变量时在其类型前边加上static修饰符

当函数离开时,静态局部变量会继续存在(不会被释放内存)并保持其值

静态局部变量的初始化只会在第一次进入这个函数时做,以后进入此函数时会保持上次离开的值

举例说明

4

# include <stdio.h>

int i;
//int * p;
void f(int);

int main(void) {
	i = 9;
	
	printf("在%s函数中 i 的值为%d\n", __func__, i);
//	printf("全局变量 p 的值为%s\n", p);
	f(i);
	
	i += 1;
	printf("在%s函数中,改变后的 i 的值为%d\n", __func__, i);
	f(i);
	
	return 0; 
}

void f(int t) {
	static int s = t;
	printf("在%s函数中 s 的值为%d\n", __func__, s);
}

输出结果为:

 

由上可以发现,第一次i的值为9时,将其传入f函数中,赋值给static int 变量s,输出s的值也为9,而当i的值改变为10时,再次传入f函数,将其值赋给s,但输出的s的值仍为9


下面再试一下,看静态变量、全局变量和局部变量分配的内存的地址在哪儿

5

# include <stdio.h>

int i;
//int * p;
void f(int);

int main(void) {
	i = 9;
	
	printf("在%s函数中 i 的值为%d\n", __func__, i);
//	printf("全局变量 p 的值为%s\n", p);
	f(i);
	
	i += 1;
	printf("在%s函数中,改变后的 i 的值为%d\n", __func__, i);
	f(i);
	
	return 0; 
}

void f(int t) {
	int j = 0;
	static int s = t; 
	printf("全局变量i的地址为:      &i = %p\n", &i);
	printf("局部静态变量的s地址为:  &s = %p\n", &s);
	printf("局部变量j的地址为:      &j = %p\n", &j);
	printf("在%s函数中 s 的值为%d\n", __func__, s);
}

输出结果为:

 

由上面的结果可以发现,局部静态变量的地址有很大差距,而它反而和全局变量分配的内存的地址相近,说明静态局部变量实际上是特殊的全局变量,而且它们位于相同的内存区域,static在这里是局部作用域的意思,即其函数内部可访问

#开头的是编译预处理指令,它不是C语言的语句,但它是不可或缺的

#define是定义了一个宏,下面给出格式:

#define 名字 值

这三者之间只有两个空格,值的后边没有空格,不要加,不然很可能出错

注意,结尾是没有分号的,因为它不是语句,名字必须是单词或字母,值可以随意(数字表达式皆可)

它是在编译器进行编译之前被处理的


下面举个例子

6

# include <stdio.h>
# define N 5

int main(void) {
  int a = 10;
  
  printf("a*N=%d\n", a * N); 
	
	return 0;
}

输出结果为:

 

由上可知,N的值为5,宏就是这样,通过#define,让N5等价,即在下面的程序中凡是出现N的地方,可以将它替换成5,这样做,是为了在写较大的程序时,使用一些数字,或许可能遗忘数字的含义,所以起一个名字替换该数字,而且,要是多次用到该数字,如果想改,需要在代码中一个个的找到,然后修改,使用宏以后,只需在程序最前边修改一次即可(注:宏定义一般是大写的字母或单词)


如果一个宏的值中有其它的宏,已久会被替换

如果一个宏的值超过一行,最后需要加\

宏后面出现的注释不会被替换 

宏不单单可以定义数字,也可以定义表达式,但定义表达式时需要注意一点,首先举个例子

7

# include <stdio.h>
# define S "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
ssssssssssssssssssssss" //这是定义一个字符串,没什么用,只为举例 说明 
# define M 3
# define N 2
# define Q M+N  //这几个宏的值没什么用,只为举例说明 

int main(void) {
	int a = 10;
  
  	printf("Q=%d\n", Q); 
    printf("Q*Q=%d\n", Q*Q);
    printf("S=%s\n", S);
	
	return 0;
}

输出结果为:

 

请看下面的输出结果,Q*Q按说应该是5*5=25,但结果却是11?这是因为,它是这么算的Q=M+N,则Q*Q=M+N*M+N,即3+2*3+2,结果为11,要向达到预期效果,定义第三个宏时后面需要加括号

当然,这只是个简单的例子,实际上可以进一步的延伸,这里就不多说了


除了自己定义宏之外,还有一些预定义宏(不需要我们再定义了),如:__FILE____LINE____DATE____TIME__ (注意:它们的两边都是两个下划线 

这些都是什么意思呢?

举个例子

8

# include <stdio.h>

int main(void) {

  	printf("__FILE__是:%s\n", __FILE__); 
  	printf("__LINE__是:%d\n", __LINE__); 
  	printf("__DATE__是:%s\n", __DATE__); 
  	printf("__TIME__是:%s\n", __TIME__); 
	
	return 0;
}

输出结果为:

 

由结果可推测一下(其实第二个也未必能猜出),第一个是源程序文件的路径

第二个是该行代码所在的行号,第三个是输出日期,第四个是输出当前时间


其实,还可以定义带参数的宏,这个用起来也有点儿像函数

带参数的宏一定要加括号,整个值也要加括号,每个参数出现的地方都要加括号

例:9

# include <stdio.h>
# define max(a,b) (a>b?a:b) //后边是表达式的话,最好带着括号 

int main(void) {
	int i = 4, j = 7;  //仅仅是举例 
	printf("较大的数为:%d\n", max(i,j));
	
	return 0;
}

输出结果为:

 

这是个带参数的宏,它的后边是一个三目运算符,表示ab两个值中的较大的数,看printf中的max(i,j),是不是像个函数调用?其实这里功能一样


【所有代码均在windows系统下dev c++下运行通过】

(如有错误,敬请指正)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值