switch语句中的变量定义

在下面的代码中,为什么变量i没有赋值1

#include <stdio.h>      

int main(void)
{   
    int val = 0;
    switch (val) {         
        int i = 1;   //i is defined here

        case 0:
            printf("value: %dn", i);
            break;
        default:
            printf("value: %dn", i);
            break;
    }
    return 0;
}

当我编译时,虽然int i = 1;但我得到了一个关于i没有被初始化的警告int i = 1; 明确地初始化它

$ gcc -Wall test.c
warning: ‘i’ is used uninitialized in this function [-Wuninitialized]
    printf("value %dn", i);
    ^

如果val = 0 ,那么输出为0

如果val = 1或其他任何值,那么输出也是0。

请向我解释为什么变量i是在交换机中声明但未定义的。 标识符为i的对象存在自动存储持续时间(在块内),但不会初始化。 为什么?


根据C标准(6.8声明和块),重点是我的:

3块允许将一组声明和语句分组为一个语法单元。 具有自动存储持续时间的对象的初始值设定项以及具有块范围的普通标识符的可变长度数组声明符将被评估,并且 每次声明为时, 值都存储在对象中 (包括在不带初始值设定项的对象中存储不确定值) 按照执行顺序达成,就好像它是一个声明一样,并且在每个声明中按声明符出现的顺序排列。

和(6.8.4.2 switch语句)

4 switch语句使控制跳转到 ,进入或超出作为开关主体的语句,具体取决于控制表达式的值以及默认标签的存在以及其中的任何情况标签的值开关机构。 一个案例或默认标签只能在最近的封闭开关语句中访问。

因此,变量i的初始值决不会因为声明而被评估

  switch (val) {         
      int i = 1;   //i is defined here
      //...

由于跳转到个案标签而未按执行顺序到达,并且像自动存储持续时间的任何变量具有不确定的值。

另请参见6.8.4.2/7中的这个规范示例:

示例在人工程序片段中

switch (expr) 
{ 
    int i = 4;
    f(i); 

case 0: 
    i = 17; /* falls through into default code */ 
default:
    printf("%dn", i); 
}

标识符为i的对象以自动存储持续时间(在块内)存在,但从不初始化,因此如果控制表达式的值不为零,则对printf函数的调用将访问不确定的值。 同样,无法达到函数f的调用。


在val不为零的情况下,执行直接跳转到标签默认值。 这意味着在块中定义的变量i未被初始化,并且其值是不确定的。

6.8.2.4 switch语句

  • switch语句会根据控制表达式的值以及交换机上或交换机上是否存在默认标签和任何外壳标签的值,导致控制跳转到,进入或通过作为交换机主体的语句身体。 一个案例或默认标签只能在最近的封闭开关语句中访问。

  • 事实上,你的i是在switch块内部声明的,所以它只存在于switch内部。 然而,它的初始化永远不会达到,所以当val不为0时它保持未初始化。

    它有点像下面的代码:

    {
       int i;
       if (val==0) goto zerovalued;
       else goto nonzerovalued;
       i=1; // statement never reached
       zerovalued:
         i = 10;  
         printf("value:%dn",i);
         goto next;
      nonzerovalued:
         printf("value:%dn",i);
         goto next;
      next:
         return 0;
     }
    

    直觉上,可以将原始声明想象为向编译器询问某个位置(在调用堆栈中的调用帧中,或者在寄存器中,或其他地方),并将初始化看作是赋值语句。 两者都是单独的步骤,你可以看看C中的初始化声明,如int i=1; 作为原始声明的语法糖int i; 接着是初始化赋值i=1;

    (实际上,事情稍微复杂一些,例如int i= i!=i;在C ++中更复杂)

    链接地址: http://www.djcxy.com/p/84443.html

    上一篇: Variable definition inside switch statement

    下一篇: Undefined variable when initialized in switch statement?