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 是局部变量,不可以在全局区定义

 

posted @ 2017-03-21 10:39  ren_zhg1992  阅读(1751)  评论(0)    收藏  举报