2016-10-03 79 views
0

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

在这两种GCC 4.9和3.5铛下面的程序编译和运行而不会出现错误:

#include "stdio.h" 

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

在GCC它输出0和在铛32767(这是最大的正2字节的整数值)。

为什么这不会导致编译错误?这是否适用于任何特定的C规范?其行为是否明确未定义?

+2

在MSVC中,它输出“警告C4700:未初始化的本地变量'x'used”。在提出愚蠢的问题之前,请启用编译器警告。 –

+1

@WeatherVane:编译器发出警告的事实不会告诉你它是否有效。 –

+0

MSVC输出在运行时'-1373317485'嗯,一次,各种值。 –

回答

4
int x = x; 

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

Any other identifier [other than a struct, union, or enum tag, or an enum constant] has scope that begins just after the completion of its declarator.

声明符在这种情况下是int x

这使得喜欢的事情:

int x = 10, y = x + 1; 

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

行为未定义的显式声明在N1570 6.3.2.1第2段中,它描述了左值(指定对象的表达式)到存储在该对象中的值的“转换”。

Except when [list of cases that don't apply here], an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion.
[...]
If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.

有问题的对象是初始值设定项中引用的x。此时,没有给x赋值,所以表达式具有未定义的行为。

实际上,如果启用足够高的警告级别,您可能会收到编译时警告。实际行为威力是一样的,如果你遗漏了初始化:

int x; 

但不要指望它。

+0

如果代码是'unsigned char x = x;',它会有所作为吗? [C11 6.2.6.2 1] – chux

+0

这一切都是正确的,但它有点回避了这个问题。您可以使用自引用初始化来构造循环列表,例如:'struct node {int value; struct node * next,* prev;} x =(struct node){argc,&x,&x};'。据我所知,这是合法的,并产生预期的结果。 – rici

+0

@chux:我不这么认为。 6.3.2.1p2仍然适用。 –

1
int x = x; 

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

+0

任何参考标准,将显示此?我直觉地认同你,这是未定义的行为。不过,拥有权威来源将是一件好事。 – Sjlver

+1

由于值是不确定的,因此它是右值转换的左值。 –

+0

@Sjlver,我找不到比dasblinkenlight引用的更多的东西。 –

1

锵也提醒一下:

$ 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; 
     ~ ^

所以我想这是不确定的行为。

+1

这是一个很好的猜测,但它仍然只是一个猜测。 –

2

根据该语言规范

6.7.8.10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.

此外,它说

6.7.8.11 The initializer for a scalar shall be a single expression, optionally enclosed in braces. The initial value of the object is that of the expression (after conversion).

因此,初始化表达式(x到的=右侧)的值是不确定,所以我们正在处理未定义的行为,因为初始化器从变量x中读取具有不确定性的值。

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

+0

您错过了导致未定义行为的部分。 –

+0

@DavidSchwartz - 不会“它的价值是不确定的。”等于UB? – KevinDTimm

+0

@KevinDTimm不是马上。有一个不确定的值是不是UB,只要你没有在分配之前阅读它。这就是为什么我编辑答案来澄清大卫的观点。 – dasblinkenlight

相关问题