1. 局部变量:
局部变量也叫自动变量, 它声明在函数开始, 生存于栈, 它的生命随着函数返回而结束.
#include <stdio.h> int main(void) { auto int i = 9; /* 声明局部变量的关键字是 auto; 因可以省略, 几乎没人使用 */ printf("%d\n", i); getchar(); return 0; }
2. 全局变量:
全局变量声明在函数体外, 一般应在函数前; 每个函数都可以使用它, 不过全局变量应尽量少用.
#include <stdio.h> void add(void); void mul(void); int gi = 3; /* 全局变量 */ int main(void) { printf("%d\n", gi); /* 3 */ add(); printf("%d\n", gi); /* 5 */ mul(); printf("%d\n", gi); /* 10 */ getchar(); return 0; } void add(void) { gi += 2; } void mul(void) { gi *= 2; }
全局变量会被初始化为空, 而局部变量在没有赋值前是一个垃圾值:
#include <stdio.h> int gi; /* 全局变量 */ int main(void) { int i; /* 句柄变量 */ printf("%d, %d\n", gi, i); getchar(); return 0; }
当全局变量与局部变量重名时, 使用的是局部变量:
#include <stdio.h> int a = 111, b = 222; int main(void) { int a = 123; printf("%d,%d\n", a, b); /* 123,222*/ getchar(); return 0; }
3. static 关键字:
用 static 关键字修饰的局部变量是静态局部变量;
静态局部变量存值如同全局变量, 区别在于它只属于拥有它的函数; 它也会被初始化为空.
#include <stdio.h> void fun1(void); void fun2(void); int main(void) { int i; for (i = 0; i < 10; i++) fun1(); printf("---\n"); for (i = 0; i < 10; i++) fun2(); getchar(); return 0; } void fun1(void) { int n = 0; /* 一般的局部变量 */ printf("%d\n", n++); } void fun2(void) { static int n; /* 静态局部变量; 会被初始化为空 */ printf("%d\n", n++); }
用 static 关键字修饰的全局变量是静态全局变量; 静态全局变量只能用于定义它的单元.
//譬如在 File1.c 里面定义了: static int num = 99; /* 去掉前面的 static 其他单元才可以使用 */ //在 File2.c 里使用: #include <stdio.h> extern int num; int main(void) { printf("%d\n", num); getchar(); return 0; }
用静态变量记录函数被调用的次数:
#include <stdio.h> int fun(void); int main(void) { int i; for (i = 0; i < 10; i++) { printf("函数被调用了 %2d 次;\n", fun()); } getchar(); return 0; } int fun(void) { static int n; return ++n; }
4. 寄存器变量(register):
书上说寄存器变量会尽量把变量放到寄存器(而不是栈或堆), 从而加快存取速度, 我试了一下, 效果一般般.
#include <stdio.h> #include <time.h> #define TIME 1000000000 int m, n = TIME; /* 全局变量 */ int main(void) { time_t start, stop; register int a, b = TIME; /* 寄存器变量 */ int x, y = TIME; /* 一般变量 */ time(&start); for (a = 0; a < b; a++); time(&stop); printf("寄存器变量用时: %d 秒\n", stop - start); time(&start); for (x = 0; x < y; x++); time(&stop); printf("一般变量用时: %d 秒\n", stop - start); time(&start); for (m = 0; m < n; m++); time(&stop); printf("全局变量用时: %d 秒\n", stop - start); getchar(); return 0; }
4. extern 关键字:
使用外部全局变量应该用 extern 重新声明一下;
如果不使用 extern, 将是重新定义;
在链接阶段, 同一程序中不同单元的全局变量是共用的所以不能重新定义;
本例为了省事并没有涉及另一个文件, 只是把变量放在文件尾模拟了一下.
另外, extern 主要还是用于函数.
#include <stdio.h> extern int g1; int main(void) { extern int g2; printf("%d,%d\n", g1,g2); getchar(); return 0; } int g1 = 77; int g2 = 88;
5. volatile 关键字:
程序在使用变量时, 特别是连续多次使用变量时, 一般是载入寄存器, 直接从寄存器存取, 之后再还回内存;
但如果此变量在返回内存时, 假如内存中的值已经改变了(从外部修改了)怎么办?
为了避免这种情况的发生, 可以用 volatile 说明此变量, 以保证变量的每次使用都是直接从内存存取.
但这样肯定会影响效率, 幸好它并不常用.
另外: 如果 const volatile 同时使用, 这表示此变量只接受外部的修改.
#include <stdio.h> volatile int num = 123; int main(void) { printf("%d\n", num); getchar(); return 0; }
6. restrict 关键字:
restrict 有点和 volatile 相反; 不过 restrict 只是对指针.
好像 C++Builder 2009 并不支持它, 暂时无法测试.