C语言进阶——变量属性05
C语言变量属性:
- C语言的变量可以有自己的属性
- 在定义变量的时候加上“属性”关键字
- “属性”关键字指明变量的特有意义
- 语法:property type value_name;
auto关键字:
- auto即c语言中局部变量的修饰属性
- auto表明在被修饰的变量存贮于栈上
- 编译器默认所有的局部变量都是auto类型的
register关键字:
- register关键字指明将局部变量存贮于寄存器中
- register只是请求寄存器变量,但是不一定成功
- register变量必须是CPU寄存器可以接受的值
- 不能用取地址符号&获取register变量的地址
static关键字:
- static关键字指明变量的“静态属性”:static修饰的局部变量存贮在程序静态区
- static关键字同时具有“作用域限定符”的意义:static修饰的全局变量和函数作用域只是声明的文件中
代码示例1:
1 #include <stdio.h> 2 3 int f1() 4 { 5 int r = 0; 6 7 r++; 8 9 return r; 10 } 11 12 int f2() 13 { 14 static int r = 0; 15 16 r++; 17 18 return r; 19 } 20 21 22 int main() 23 { 24 auto int i = 0; // 显示声明 auto 属性,i 为栈变量 25 static int k = 0; // 局部变量 k 的存储区位于静态区,作用域位于 main 中 26 register int j = 0; // 向编译器申请将 j 存储于寄存器中 27 28 printf("%p\n", &i); 29 printf("%p\n", &k); 30 printf("%p\n", &j); // error 31 32 for(i=0; i<5; i++) 33 { 34 printf("%d\n", f1()); 35 } 36 37 for(i=0; i<5; i++) 38 { 39 printf("%d\n", f2()); 40 } 41 42 return 0; 43 }
其中第33行会出错,因为不能对寄存器变量进行取地址操作;
代码示例2:
1 #include<stdio.h> 2 3 register int a=9;//error 4 int main() 5 { 6 return 0; 7 }
第3行会出错,因为寄存器的内存非常有限,他不可能让一个全局变量一直占用这个资源。
extern关键字:
extern用于声明“外部”定义的变量和函数
- extern变量在文件的其他地方分配空间
- extern函数在其他的地方定义
extern在C++里面还可以用于告诉编译器使用C方式编译,做一下了解就可以,C++编译器和一些变种C编译器会默认按照“自己”方式编译函数和变量,通过extern关键字可以命令编译器“以标准c方式进行编译”。
1 test1.c: 2 3 #include <stdio.h> 4 5 extern int getI(); 6 7 int main() 8 { 9 printf("%d\n", getI()); 10 11 return 0; 12 } 13 14 15 test2: 16 17 static int g_i; 18 19 int getI() 20 { 21 return g_i; 22 }
这里同时编译test1.c和test2.c,在test.c中使用关键字extern,然后具体的定义在test2.c里面定义,因为在test2.c中g_i,使用了static关键字修饰,所以他的作用域只能是本文件,但是在test1.c中可以用extern修饰一个函数,然后在test2.c中定义这个函数用来获得这个g_i的值
小结:
- auto变量存贮在程序的栈中,默认属性
- static变量存贮在程序静态区中
- register变量请求存贮于CPU寄存器中
- extern变量在文件的其他地方分配空间
- extern能够指示编译器按照标准C方式编译程序