C语言 我对这个区块的范围有疑问

kupeojn6  于 2023-03-01  发布在  其他
关注(0)|答案(3)|浏览(118)

下面是代码:

#include <stdio.h>

int var0 = 5;

int main() {
  int var1 = 7;
  int var2 = 9;

  printf("a) %d, %d, %d\n", var0, var1, var2);
  {
    int var1 = 17;

    printf("b) %d, %d, %d\n", var0, var1, var2);
    var0 = 15;
    var2 = 19;
    printf("c) %d, %d, %d\n", var0, var1, var2);
    {
      int var0 = 25;
      printf("d) %d, %d, %d\n", var0, var1, var2);
    }
  }
  printf("e) %d, %d, %d\n", var0, var1, var2);
}

编译器的结果是:

a) 5, 7, 9
b) 5, 17, 9
c) 15, 17, 19
d) 25, 17, 19
e) 15, 7, 19

我不理解e,如果我没弄错的话,外块对内块有影响,但是反过来就不是这样了,所以在e的情况下,只有5,7和9在外块,因此在作用域中,编译器给我的var0,15在内块,因此不在作用域中,var2也是这样,你能解释一下我的误解吗

ax6ht2ek

ax6ht2ek1#

我不明白。
var0 = 15;处,var0的唯一可见声明是在任何函数外部声明的int var0 = 5;,因此var0 = 15;中的var0引用初始的var0,并且赋值将其设置为15。
后面的int var0 = 25;声明了一个新的var0,它隐藏了前面的var0,因此用25进行初始化不会改变前面的var0,而是将其保留为15。
int var1 = 17;声明了一个新的var1,它隐藏了先前的var1,因此使用17进行初始化不会改变先前的var1,而是将其保留为7。
var2 = 19;var2的唯一可见声明是在main中声明的int var2 = 9;,因此var2 = 19;中的var2引用前面的var2,并且赋值将其设置为19。

jvlzgdj9

jvlzgdj92#

程序的变量位于以下4个scopes中:
1.文件作用域(即全局作用域)
1.外部块作用域(整个函数main的作用域)
1.中块示波器
1.最内层块作用域
程序定义以下变量:
1.文件范围中的var0,初始化为值5

  1. var0在最里面的块范围内,初始化为值25
    1.外部块范围中的var1,初始化为值7
  2. var1位于中间块范围内,初始化为值17
  3. var2,初始化为值9
    所有这五个变量都是不同的,即使它们具有相同的名称。
    在程序的后面,将变量#1的值更改为15,将变量#5的值更改为19。更改变量#1的值不会影响变量#2(将来)的值,因为如前所述,变量#1和#2是不同的,尽管它们具有相同的名称。
    这条线
var0 = 15;

将使用值15覆盖现有变量var0的值,而行

int var0 = 25;

将定义一个新变量var0,它"隐藏"了现有变量var0的名称,因此在该作用域及其嵌套子作用域中对名称var0的所有引用都指向新变量。这使得旧变量var0在这些作用域中不再直接可访问。(不过,旧变量在这些作用域中仍然可以通过指针间接访问。)
这条线

printf("e) %d, %d, %d\n", var0, var1, var2);

将打印变量#1、#3和#5。
如前所述,变量#1初始化为值5,但后来更改为值15。由于此更改发生在执行printf行之前,因此printf行将为变量#1的值打印15
如前所述,变量#3被初始化为值7,之后不会更改,因此,printf行将为变量#3的值打印7
如前所述,变量#5初始化为值9,但后来更改为值19。由于此更改发生在执行printf行之前,因此printf行将为变量#5的值打印19
因此,引用的printf行将打印以下内容:

e) 15, 7, 19

如果我没记错的话,外块对内块有影响,但反过来就不是这样了。
这个陈述是不正确的。它正好相反。但是,正如前面提到的,由于内部作用域的变量名隐藏了外部作用域的变量名,所以这种影响是有限的。
执行外部作用域时内部嵌套作用域do not exist的变量。无法访问尚不存在或生存期已结束的变量。
旁注:如果变量名隐藏其他变量名的行为是不可取的,那么您可能需要考虑配置您的编译器,以便在发生此类隐藏时发出警告。例如,在gcc和clang上,您可以使用-Wshadow命令行选项。

ujv3wf0j

ujv3wf0j3#

如果我没记错的话,外块对内块有影响,但反过来就不是这样了。
你错了。没有这样的规则。影响力是双向的。
所以在e的例子中,只有5,7和9在外部块,因此在作用域中,编译器给我的是15,它在内部块,因此不在作用域中,对于var2也一样。
块对访问不重要,它们对“作用域”很重要。作用域,就像狙击手作用域一样,定义了你能看到哪些变量。当你能看到它们时,你就能改变它们。
当你在作用域中定义另一个var1时,它会遮蔽外面的那个,所以var1在外面的作用域意味着“外面的var1”,而var1在里面的作用域意味着“里面的var1”,你可以看到外面的var1,因为里面的var1挡住了你的路。
这称为“variable shadowing“。
要理解这一点,请重命名变量以消除名称冲突:

int var0 = 5;

int main () {
    int var1 = 7;
    int var2 = 9;

    printf("a) %d, %d, %d\n", var0, var1, var2);
    {
        int var1a = 17;

        printf("b) %d, %d, %d\n", var0, var1a, var2);
        var0 = 15;
        var2 = 19;
        printf("c) %d, %d, %d\n", var0, var1a, var2);
        {
            int var0a = 25;
            printf("d) %d, %d, %d\n", var0a, var1a, var2);
        }
    }
    printf("e) %d, %d, %d\n", var0, var1, var2);
}

内部变量不存在于外部作用域中,但外部变量存在于内部作用域中。

相关问题