c中的全局变量和局部变量的初始化和定义
今天在看《程序员面试笔试宝典》时,看到变量的重定义,想起之前传智中有讲过,不过有点模糊了,现在来巩固下。
全局变量、静态全局变量、静态局部变量和局部变量的区别
变量可以分为:全局变量、静态全局变量、静态局部变量和局部变量。
(1) 按存储区域分,全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区。
(2) 按作用域分, 全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。
先来看一下全局变量:extern和static
1.extern
1 //extern 暗示变量将稍后定义,先声明这个变量存在 2 //extern 有没有都可以,为了让代码规范,需要extern 3 extern int X;//全局变量声明。。很多人会误会了一个变量定义了没有初始化 4 5 //extern 可以表示Y是一个在其他源文件的外部变量,声明以后就可以调用 6 //extern 有没有都可以,为了让代码规范,需要extern 7 extern int Y;//声明,声明是一个外部变量,在其他源文件,可以使用
2.static
(1)先来介绍它的第一条也是最重要的一条:隐藏
当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话,我举例来说明。
我们要同时编译两个源文件,一个是a.c,另一个是main.c. 下面是a.c的内容:
a.c
char a = 'A'; // global variable void msg() { printf("Hello\n"); }
main.c
int main(void) { extern char a; // extern variable must be declared before use printf("%c ", a); (void)msg(); return 0; }
程序的运行结果是:
A Hello
你可能会问:为什么在a.c中定义的全局变量a和函数msg能在main.c中使用?前面说过,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。此例中,a是全局变量,msg是函数,并且都没有加static前缀,因此对于另外的源文件main.c是可见的。
如果加了static,就会对其它源文件隐藏。例如在a和msg的定义前加上static,main.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。Static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏,而对于变量,static还有下面两个作用。
(2) static的第二个作用是保持变量内容的持久
存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。
共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的。
虽然这种用法不常见,但我还是举一个例子。
#include <stdio.h> void func(int i) { static int value = i; printf("%d\n", value); } void main() { func(0); func(1); func(2); getchar(); }
输出结果:
0
0
0
程序每次输出0,是因为value(静态变量)只会定义一次。只会在第一次调用func的时候执行 static int value = i;value就会初始化为0(此时i = 0);以后的调用func都不会再执行这条语句了。
(3) static的第三个作用是默认初始化为0.其实全局变量也具备这一属性,因为全局变量也存储在静态数据区
在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置0,然后把不是0的几个元素赋值。如果定义成静态的,就省去了一开始置0的操作。再比如要把一个字符数组当字符串来用,但又觉得每次在字符数组末尾加‘\0’太麻烦。如果把字符串定义成静态的,就省去了这个麻烦,因为那里本来就是‘\0’。不妨做个小实验验证一下。
1 #include <stdio.h> 2 3 int a; 4 5 int main(void){ 6 7 static char str[10]; 8 9 printf("integer: %d; string:(begin)%s(end)", a, str); 10 11 getchar(); 12 return 0; 13 14 }
输出;
integer: 0; string:(begin)(end)
全局变量有声明和定义,局部变量只有定义
全局变量声明可以多个
1 #include <stdio.h> 2 3 extern int X; 4 extern int X; 5 extern int X; 6 extern int X; 7 8 static int Y; 9 static int Y; 10 static int Y; 11 12 void asd(); 13 void asd(); 14 void asd(); 15 16 void asd() 17 { 18 23 } 24 25 int main() 26 {}
全局变量的声明和函数的声明一样,可以有多个,声明只是声明存在。
定义就是定义实体,只能有一个!!!
//全局变量
int Z; //定义
int Z; //重定义
int Z = 1;//定义 int Z = 2;// error:重定义
局部变量
int num;和 int num = 1; 都是定义
void asd() { static int z; static int z ;// error :重定义 }
int main() { int local; printf("%d\n", local);//error: 使用了未初始化的局部变量 getchar(); }
总结:
1.全局变量可以多个声明,但是只能有一个定义
2.局部变量声明和定义一样
3.全局变量会被编译器默认初始化为0
4.局部变量不初始化就使用,编译器会报错。
5.auto 是局部变量,不可以在全局区定义

浙公网安备 33010602011771号