在同一函数中定义变量及其静态等价物

时间:2018-01-31 10:16:59

标签: c++ c scope static shadowing

我不明白以下代码的工作原理:

id="Picture"

使用Clang或GCC编译的代码打印以下输出:

Observable.range(0,50)
    .subscribeOn(Schedulers.computation())
    .delay(1000, TimeUnit.MILLISECONDS)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(integer -> mProgressBar.setProgress(integer));

有人可以向我解释这里发生了什么吗?看起来在一条指令中实现了两次操作并且不止一次。是不确定的行为? 我在C ++中观察到相同的行为。

3 个答案:

答案 0 :(得分:24)

这不是未定义的行为。

#include "stdio.h"

int main(void) {
  int i = 3; //first i
  while(i--) {
    static int i = 100; //second i
    i--,
    printf("%d\n", i);
  }
  return 0;
}

在while循环体中,大多数本地i(第二i)是首选。在while循环中检查条件时,它不知道身体中有什么。因此,首先选择i是没有问题的。

答案 1 :(得分:11)

维基百科对此非常突出:

  

在计算机编程中,当在特定范围内声明的变量(决策块,方法或内部类)与在外部范围内声明的变量具有相同的名称时,会发生变量阴影。在标识符(名称而不是变量)的级别上,这称为名称屏蔽。该外部变量被称为由内部变量遮蔽,而内部标识符被称为掩盖外部标识符。

现在,在块内部,它找到静态变量并对其进行处理,但while条件会减少i,这是在块外声明的值。范围不同 - 使用i的正确值是没有问题的。这是合法的C代码,但不一定是写东西的好方法。

实际上这样做gcc -Wshadow progname.c会给出

progname.c: In function 'main':
progname.c:7:20: warning: declaration of 'i' shadows a previous local [-Wshadow]
         static int i=2;
                    ^
progname.c:5:9: warning: shadowed declaration is here [-Wshadow]
     int i=2;
         ^

来自标准§6.2.1p4

  

...如果标识符指定同一名称空间中的两个不同实体,则范围可能会重叠。如果是这样,一个实体(内部范围)的范围将严格地在另一个实体(外部范围)的范围之前结束。 在内部范围内,标识符指定在内部范围内声明的实体;在外部范围内声明的实体在内部范围内隐藏(并且不可见)

答案 2 :(得分:2)

可以在嵌套范围内声明相同的命名变量。编译器将它们视为不同的变量。这非常令人困惑,但每次访问的变量都是在最大范围内声明的变量。 while之外是int i = 3;,里面是static int i = 100;

#include "stdio.h"

int main(void) {
  int i = 3; // outer i
  while(i--) { // outer i
    static int i = 100; // inner i
    i--, // inner i
    printf("%d\n", i); // inner i
  }
  return 0;
}

如果这是main之外的函数,则第二次调用它将产生

96
95
94

依旧......