作用域(scope)
参考:C Primer Plus 第6版 第12章 存储类别、链接和内存管理
1. 分类
2. block scope / 块作用域
2.1. 定义
- block / 块 是用一块花括号括起来的代码区域
- 块作用域变量的范围是从定义处到包含该定义块的末尾
- 声明在内层块中的变量,其作用域仅局限于该声明所在的块
2.2. 函数的形式参数
虽然函数的形式参数声明在函数的花括号之前,但是它们也具有块作用域,属于函数体这个块。
// 形参 a 和 b 属于 function 函数这个块,
// 作用域仅局限于该函数
void function(int a, int b){
return a+b;
}
2.3. 块中的变量定义
之前,具有块作用域的变量都必须声明在块的开头。C99 标准放开了这个限制:允许在块中的任意位置定义变量。
因此,for 循环语句的代码可以写成如下形式:
// 形参 a 和 b 属于 function 函数这个块,
// 作用域仅局限于该函数
for(int i=0; i<10; i++)
{
printf("loop 1: n = %d\n", n);
}
2.4. 块作用域的嵌套
#include <stdio.h>
int main()
{
int n = 8;
printf("Initially, n = %d at %p\n", n, &n);
for (int n = 1; n < 3; n++) // loop1
printf("loop 1: n = %d at %p\n", n, &n);
printf("After loop 1, n = %d at %p\n", n, &n);
for (int n = 1; n < 3; n++) // loop2
{
printf("loop 2 index n: n = %d at %p\n", n, &n);
int n = 6;
printf("loop 2: n = %d at %p\n", n, &n);
n++;
}
printf("After loop 2, n = %d at %p\n", n, &n);
return 0;
}
该程序的输出如下:
Initially, n = 8 at 000000950FDFF6D4
loop 1: n = 1 at 000000950FDFF6F4
loop 1: n = 2 at 000000950FDFF6F4
After loop 1, n = 8 at 000000950FDFF6D4
loop 2 index n: n = 1 at 000000950FDFF714
loop 2: n = 6 at 000000950FDFF734
loop 2 index n: n = 2 at 000000950FDFF714
loop 2: n = 6 at 000000950FDFF734
After loop 2, n = 8 at 000000950FDFF6D4
分析:
- 最开始打印的是最早定义的局变量 n;
- 进入循环 loop1 之后,隐藏了原有的 n,打印的是 loop1 循环定义的索引 n;
- 循环 loop1 退出之后,打印的变量变为局变量 n;
- 进入循环 loop2 之后,隐藏了原有的 n,打印的是 loop2 循环定义的索引 n;
- 然后在循环体中又声明了一个局变量 n,隐藏了索引 n;
- 循环单次迭代结束之后,声明在循环体中的 n 消失,循环头仍调用到索引 n;
- 循环 loop1 退出之后,打印的变量重新变为最早定义的局变量 n。
简而言之,索引n的作用域是整个循环,而定义在循环体中变量n的作用域只有单个循环。
3. function scope / 函数作用域
- 仅用于goto语句的标签
- 即使一个标签首次出现在函数的内层块中,它的作用域也将延伸至整个函数(是整个函数而非块)
- 标签的函数作用域防止在两个块中使用相同的标签所导致的混乱
4. function prototype scope / 函数原型作用域
参考博客:四种作用域 - CSDN - weixin_45708424(但是这篇博客函数作用域部分的解释与书中不一致,仅参考函数原型作用域这部分)
- 用于函数原型中的形参名
- 函数原型作用域的范围是从形参定义处到原型声明结束(可以理解为小括号内)
- 函数原型声明中的标识符可以与函数定义中说明的标识符名称不同,只要让函数声明和函数定义中小括号内每个变量的类型及数目一致即可,也可以省略掉参数名。
double max(double x, double y);
double max(double num_1, double num_2);
double max(double, double);
// 三者均可
double max(double x, double y){
if(x<y){
return y;
}else{
return x;
}
}
5. file scope / 文件作用域
- 从定义处到该定义所在的文件末尾均可见
- 文件作用域变量也被称作全局变量 global variable