【问题标题】:What exactly is the difference between blocks and loops?块和循环之间到底有什么区别?
【发布时间】:2020-08-14 07:33:16
【问题描述】:

代码 1: 没有警告 - 没有错误...一切正常

#include <stdio.h>

int main()
{
    int r = 1;
    printf("using %d\n", r);

    for (int k = 1; k <= 2; k++)
    {
       int r = r * 2;
    }

    return 0;
}

代码 2: 错误

#include <stdio.h>

int main()
{
    int cnt = 1;
    printf("using %d\n", cnt);
    
    {
        int cnt = cnt * 2;
    }

    return 0;
}

编译器响应:

'cnt' is used uninitialized in this function [-Werror=uninitialized]
       int cnt = cnt * 2;

所以,我知道在这种情况下 loopblock 之间存在一些区别,但我无法弄清楚。谁能告诉我scope of a variable 在这里是如何工作的?

【问题讨论】:

标签: c


【解决方案1】:

它们都有完全相同的问题,即rcnt 在各自的程序中都是自初始化的。

这可能是未定义,因为如果它们碰巧具有陷阱表示,则使用未初始化的变量(具有不确定的值)。

gcc 碰巧在一种情况下检测到它,而在另一种情况下则没有。 gcc-Wuninitialized -Winit-self 选项,但即使有这些选项,它仍然无法检测到第一种情况。无论如何,问题仍然存在(并且相同)。

【讨论】:

  • 你能解释一下为什么在第一种情况下,int r = r * 2; 语句的末尾,r 的值是 0 吗?是因为价值不定吗?
  • 是的,0 也可以是一个不确定的值。一般来说,when 完全使用未定义的未初始化变量是无关紧要的 - 因为没有理智的方法来解释该代码/程序(这不会与保证初始化为的具有静态存储的对象混淆0 即使没有提供初始化器,例如全局变量、static int i; 任何地方等)。
  • 有道理。那么总结一下如果不是编译器错误,现在应该如何解释第一种情况的行为?
  • 外部范围变量与问题并不特别相关,因为由于rcnt(具有相同名称的变量)的声明,它们在内部范围中不可见。它本身不是编译器错误,因为编译器不需要为未定义的行为发出诊断(警告/错误)。具体来说,编译器需要发布约束违规诊断;对于其他人,如 UB、程序员错误等,他们可能会警告说会有所帮助 - 但不是必需的。
  • @SaiSreenivas 你的意思是像godbolt.org/z/Y8q8ME这样的东西吗?是的,printf 在这里是可以的,因为此时只有一个cnt(因此不涉及重叠范围)。但要注意UB can time-travel - 如果程序unconditionally 的某些部分显示 UB,则称整个程序包含 UB。
猜你喜欢
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
相关资源
最近更新 更多