3. 局部变量和全局变量
3.1、局部变量
局部变量 是指函数内部声明(没有用 static修饰)的变量和函数的形参变量。
说明:
- 局部变量只有在函数运行期间被创建,函数运行结束,局部变量自动销毁,对应的内存空间也是释放待下个函数调用时使用。
- 局部变量存在于栈(Stack)上,在函数调用时,形参变量会压栈并使用,在函数调用结束后,此变量会弹栈释放。
示例:
#include <stdio.h>
int myadd(int x, int y) {
int r; // x, y, r 都是局部变量。
r = x + y;
return r;
}
int main(int argc, char *argv[]) {
int result; // argc, argv 和 result 也是局部变量。
result = myadd(1, 5); // 调用时在栈上创建 x、y、r变量
// myadd 函数调用结束,myadd 内部的x、y、r 变量销毁
printf("result:%d\n", result);
return 0;
}
3.2、全局变量
全局变量 是指函数外部,.c 文件内部声明的变量。全局变量的特点是所有的函数可以不通过传参可以直接引用其变量。方便全局数据的存储。
说明:
- 全局变量会在程序启动时自动创建并赋初始值。
- 全局变量如果没有给出初始值,则初始值默认0值(具体要看编译器)。
- 全局变量存在程序的数据段,它会在整个程序执行过程中一直存在,在程序退出后才销毁。
- 通常未初始化的全局变量放在程序数据段的
BSS段(根据操作系统不同而不同)。 - 通常已初始化的全局变量或静态局部变量(后面会讲)放在程序数据段的
初始化数据段(根据操作系统不同而不同)。
- 通常未初始化的全局变量放在程序数据段的
- 在程序内有同名的全局变量和局部变量,在函数内部优先访问局部变量而非全局变量(由 C 语言的作用域决定)。
- 全局变量在没有
static关键字修饰的情况下,为整个程序内全局。即其他的.c文件也能够访问此变量,且不可重复声明。 - 任何一个函数都有可能改变全局变量的值,因此要慎重使用全局变量。
一个程序优先访问离自己最近的复合语句或函数内的局部变量,如果局部变量不存在才访问全局变量,如果全局变量也不存在则程序编译时报错。
示例:
#include <stdio.h>
// week 数组为全局变量的数组
const char * week[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
int call_count = 0; // call_count 为 int 型全局变量
int myadd(int x, int y) {
call_count += 1;
return x + y;
}
int main(int argc, char *argv[]) {
myadd(1, 2);
myadd(3, 4);
printf("myadd 函数共调用 %d 次\n", call_count);
printf("today is %s\n", week[1]);
return 0;
}
程序运行结果如下:
myadd 函数共调用 2 次
today is Mon
计算机程序在运行时,大致分为如下几部分:
- 栈(Stack)
- 堆(Heap)
- 数据段(Data)
- 初始化的数据
- 未初始化的数据(BSS)段,其数据初始值全部置零。
- 代码段(Code)
典型程序运行时的存储空间安排如下图所示:
+---------------+
high address | argv[] | 命令行参数和环境变量
+---------------+
| stack | 栈
| - - - - - - - |
| | |
| V |
| |
| |
| ^ |
| | |
| - - - - - - - |
| heap | 堆
+---------------+
| bss | 未初始化的全局变量
+---------------+
|initalized data| 初始化的全局数据
+---------------+
low address | code | 代码段
+---------------+
其中,代码段用来存储函数编译后的二进制指令;bbs 和 initalized data 存放全局变量;heap 存放动态分配内存的数据;stack 用于存放函数内的局部变量。
练习:
写一个函数 factorial 求一个整数 n 的阶乘。
要求函数的定义格式如下:
int factorial(int n) {
...
}
在数学中 n 的阶乘用 n! 表示,即:
n! 等于 1 * 2 * 3 * ... * n-1 * n 的积。
如:
0!等于11!等于12!等于1*2等于23!等于1*2*3等于6- 以此类推。