在同一语句中声明和使用变量

时间:2016-10-03 20:47:48

标签: c

在C中,在声明它的同一语句中使用变量是否有效?

在gcc 4.9和clang 3.5中,以下程序编译并运行且没有错误:

#include "stdio.h"

int main() {
  int x = x;
  printf("%d\n", x);
}

在gcc中输出0和clang 32767(最大的正2字节整数值)。

为什么这不会导致编译错误?这在任何特定的C规范中都有效吗?它的行为是否明确未定义?

4 个答案:

答案 0 :(得分:4)

int x = x;

这是"有效"从某种意义上说它不违反约束或语法规则,因此不需要编译时诊断。名称x在初始化程序中可见,并引用正在声明的对象。范围在N1570 6.2.1第7段中定义:

  

任何其他标识符 [除了struct,union或enum标记,或   枚举常量] 具有在完成后立即开始的范围   它的声明者。

在这种情况下,声明者int x

这允许这样的事情:

int x = 10, y = x + 1;

但是声明具有未定义的行为,因为初始化器指的是一个尚未初始化的对象。

行为未定义的明确声明在N1570 6.3.2.1第2段中,该段描述了"转换"左值(指定对象的表达式)与存储在该对象中的值的对比。

  

[不适用于此处的案例列表] 外,   没有数组类型的左值将转换为存储的值   在指定的对象中(并且不再是左值);这就是所谓的   左值转换
   [...]
  如果左值指定一个自动存储持续时间的对象   可以使用 register 存储类声明(从不   得到了它的地址),并且该对象未初始化(未声明   使用初始化程序并且之前未执行任何赋值   使用),行为未定义。

有问题的对象是x,在初始化程序中引用。此时,没有为x分配任何值,因此表达式具有未定义的行为。

实际上,如果启用足够高的警告级别,您可能会收到编译时警告。实际行为可能与省略初始化程序相同:

int x;

但不要指望它。

答案 1 :(得分:2)

根据语言规范

  

6.7.8.10如果没有明确初始化具有自动存储持续时间的对象,则其值是不确定的。

此外,它说

  

6.7.8.11标量的初始值设定项应为单个表达式,可选择用大括号括起来。对象的初始值是表达式的初始值(转换后)。

因此,初始化表达式(x右侧的=)的值是 indeterminate ,因此我们正在处理未定义的行为,因为初始化程序从变量读取x具有不确定的价值。

各种编译器提供警告设置以捕获这些条件。

答案 2 :(得分:1)

int x = x;

导致未定义的行为。不要指望任何可预测的行为。

答案 3 :(得分:1)

Clang确实警告过:

$ clang -c -Wall ub_or_not_ub.c
ub_or_not_ub.c:4:11: warning: variable 'x' is uninitialized when used within its own initialization [-Wuninitialized]
  int x = x;
      ~   ^

所以我猜它是未定义的行为。