11-1. 标识符作用域

  • 学习人数 30K+
  • 适合所有人群学习
avatar
林耿亮

你好编程主讲老师

1. 作用域

#include <stdio.h>
void func()
{
    int n;
    n = 100;
    printf("n in func %d\n", n);
}

int main()
{
    int n = 0;
    printf("n in main %d\n", n);
    func();
    printf("n in main %d\n", n);
    return 0;
}

main函数中有一个变量名为n的变量,其值为0。而在函数func中,也有一个变量名为n的变量,并将其赋值为100。

程序运行结果如下:

两个函数中的变量独立

函数main中的变量n始终为0,而函数func中的变量n被赋值为100。

通过结果看来,函数func中的变量n,与函数main中的变量n,并不是同一个变量。下面,让我们引入作用域的概念,更加明确地描述并解释这个现象。

2. 块作用域

首先,我们从代码块开始。

{
    //  代码块A
    xxxxxxxxxxx
    xxxxxxxxxxx
    xxxxxxxxxxx
}

{
    //  代码块B
    xxxxxxxxxx
    xxxxxxxxxx
    xxxxxxxxxx
}

源代码中,被花括号包括的代码,形成一个代码块

如果,我们在代码块A中声明一个整型变量int n = 3。看看编译器是怎样理解这条声明的。

{
    //  代码块A
    xxxxxxxxxxx
    int n = 3;
    xxxxxxxxxxx
}

声明具有三层意义:

  1. 编译器预留sizoef(int)字节的内存空间。
  2. 标识符n指代上述的内存空间。
  3. 标识符nint类型,用于规范所指代内存空间中数据的使用。

编译器看到这条声明之后,将会为我们预留4字节内存空间。技术上来说,在代码中可以使用这个空间的地址和空间大小来指代该空间。但是,这是汇编语言惯用的写法。而我们使用C语言,就是为了可以通过更方便的方式来操作内存。在C语言中,使用声明变量时的标识符n来指代这个空间。此外,编译器还认为标识符nint类型。当对n做出一些不正常操作时,例如:将n当做指针来使用,会报错或警告提示我们。

使用标识符n来指代内存空间有一定的使用范围。若声明在代码块内,使用范围从变量声明开始,一直到包含声明的代码块结束。这一段使用范围被称之为标识符n块作用域

作用域的范围

块作用域有上下两个界限:

  1. 上界限:标识符声明
  2. 下界限:包含标识符声明的代码块结束

作用域外标识符n没有意义。

对于上界限来说,在标识符n声明前,无法使用标识符n。这也是我们之前老生常谈的标识符先声明后使用的原则

对于下界限来说,包含标识符声明的代码块结束后,标识符n没有意义。因此,在代码块B中,也无法使用标识符n

代码块结束后

若在同一代码块中重复声明标识符n,将出现标识符重定义报错。

#include <stdio.h>

int main()
{
    int n;
    printf("%d", n);

    int n;  //  标识符重定义
    printf("%d", n);
    return 0;
}

第一条声明语句已经让标识符n指代了一个数据对象了,它不能再去指代别的数据对象了。

标识符重定义