在一行中初始化C中的所有变量和未初始化的值

Initializing all variables in C in one line and uninitialized value

在C语言中,就是

int x, y, z = 0;

和这个一样吗?

int x = 0;
int y = 0;
int z = 0;

此外,如果我只说int a;,似乎a的值即使未初始化也为零,但并非如What will be the value of uninitialized variable?[=15中所述未定义=]

不,两者不等价。

int x, y, z = 0;

在这一行中 xy 将具有不确定的值,而 z 被初始化为零。

不过,您可以将其保留在 "one line" 中,但要付出一些冗长的代价:

int x = 0, y = x, z = y;

现在所有三个都使用相同的值(您给的值x)进行了初始化。要用一个变量初始化另一个变量,只需预先定义初始化器即可。即使在同一条线上也能正常工作。上面的内容还可以让您很容易地更改所有变量的初始值。

或者,如果你觉得之前的样式很丑,你可以改成两行:

int x, y, z;
x = y = z = 0;

但现在是赋值,而不是初始化。

Also, if I just say int a;, it seems that the value of a is zero even if it is uninitialized, but not undefined as described in What will be the value of uninitialized variable?

"Indeterminate value" 并不意味着 "not-zero"。零并没有使它成为变量初始值的无效候选者。一些 "helpful" 编译器将调试版本中的初始化变量置零。如果您不注意编译器警告,它可能会隐藏严重的错误。

这个:

int x, y, z = 0;

不一样
int x = 0, y = 0, z = 0;

int x = 0;
int y = 0;
int z = 0;

在第一种情况下,只有 z 会被初始化,而在后两种情况下 - 所有三个。

如果值没有被初始化,它的值是不确定的,读取未初始化的变量是未定义的行为——读取它之后它似乎有值 0 的事实是 undefined behavior.

的结果

这样的陈述
 int x, y, z = 0;

只初始化最后一个变量,zxy 保持未初始化状态。

可能相当于

int x = 0;
int y = 0;
int z = 0;

会是

int x, y, z;
x = y = z = 0;

也就是说,

Also, if I just say int a;, it seems that the value of a is zero even if it is uninitialized

视情况而定,如果变量具有静态存储持续时间,它将隐式初始化为0。

第一个问题的答案是"no",只有显式初始化的变量才会被赋值。其他的可能有任何值,(包括零)。

回答您的第二个(更有趣的)问题(也许值得单独提问):

术语“unitialised”只是意味着在实例化时没有显式赋值;该值是当时恰好位于相关内存位置的任何值。一些环境在执行开始时用零填充堆栈,因此在简单的示例中可能为零。然而,它不会一直如此,因为堆栈在执行期间会被搅动,并且包含以前执行的代码遗留下来的不同值。

例如,在下面的示例中,fn() 中的 a 可能不会在每次调用(或任何调用)中都为零,并且会在调用之间发生变化:

void fn()
{
    static int i = 1 ;
    volatile int a ;
    printf( "Call %d: a = %d\n", i, a ) ;
    i++ ;
    a = i ;
}

int main()
{
    for( int i = 0; i < 10; i++ )
    {
        fn() ;
    }
}

在我的测试中(在 ideone.com)它输出以下内容:

Call 1: a = 134513970
Call 2: a = 2
Call 3: a = 3
Call 4: a = 4
Call 5: a = 5
Call 6: a = 6
Call 7: a = 7
Call 8: a = 8
Call 9: a = 9
Call 10: a = 10

正如您在第二次和后续调用中看到的那样,它包含上一次调用在该位置留下的所有内容,因为 相同 堆栈位置被重用。不同的调用模式——例如,在 fn() 之前或之后插入一个函数调用,当该堆栈区域被其他函数重用时,将产生不同且更不可预测的结果。例如,当我如下修改循环体时:

        rand() ;
        fn() ;

结果是:

Call 1: a = 1433091188
Call 2: a = 1433091188
Call 3: a = 1433091188
Call 4: a = 1433091188
Call 5: a = 1433091188
Call 6: a = 1433091188
Call 7: a = 1433091188
Call 8: a = 1433091188
Call 9: a = 1433091188
Call 10: a = 1433091188