switch语句出现问题

3

让我们通过代码来看这个问题:

代码-1

#include <stdio.h>

int main(int argc, char *argv[])
{
    int a =1;
    switch (a)
    {
        printf("This will never print\n");
    case 1: 
        printf(" 1");
        break;
    default:
        break;
    }   
    return 0;
}

这里的printf()语句永远不会执行 - 可以看看http://codepad.org/PA1quYX3。但是

代码2

#include <stdio.h>
int main(int argc, char *argv[])
{
    int a = 1;
    switch (a)
    {
        int b;
    case 1:
        b = 34; 
        printf("%d", b);
        break;
    default:
        break;
    }   
    return 0;
}

这里将要声明int b - 请参见http://codepad.org/4E9Zuz1e

我不明白为什么在code1中printf()不执行,但在code2中int b会执行。

为什么?

编辑: 我知道int b;是声明并在编译时分配内存,因此无论控制流是否到达那里,该声明都将被执行。

现在看看这段代码

#include<stdio.h>

int main()
{
   if(1)
   {
    int a; 
   }

a =1;
return 0;
}

在控制流路径中,int a仍然是受控制的,但这段代码无法编译通过...为什么?


2
我的回答 对于 当变量定义被绕过时如何使用变量? 应该解释了正在发生的事情。 - Filip Roséen - refp
1
请注意,如果b的声明是int b = 31,则不能保证初始化会发生。printf()和声明之间的主要区别在于printf()语句是可执行的,而声明不是。 - Jonathan Leffler
2个回答

8

switch想象为带有标签的goto。不管你跳到哪里,只要变量声明在使用它的上方,你就可以使用它。这主要是因为变量声明不是像表达式那样被“执行”的可执行语句。这个switch几乎等同于:

int a  = 1;

{
    if (a == 1) goto case1;
    goto defaultcase;

    int b;

case1:
    b = 34;
    printf("%d", b);
    goto end;

defaultcase:
    goto end;

end:
}

return 0;

而且gotob的范围无关。

不过,试着这样做:

switch (a)
{
int b = 1;
....

在这种情况下,即使声明了b,初始化也将被跳过,因为那是一个可执行语句,可以执行或不执行。如果您尝试这样做,您的编译器应该会警告您。
关于在if内部进行声明(更新后的问题):在这种情况下,a的范围仅限于if。它在进入作用域时创建,并在作用域结束时销毁。

2
在这种情况下,a 作为一个仅限于 if 的范围。它在进入该范围时创建,在范围结束时销毁。请注意,switch 不会创建新的范围,就像标签和 goto 一样。 - Seth Carnegie
1
@SethCarnegie:为了反映问题的更改,应该将这个(范围/如果)添加到答案中吗? - undur_gongor
如果你认为需要的话,我明天会添加它,或者如果你有时间和精力,你也可以添加。任何人都可以编辑我的答案,欢迎参与。 - Seth Carnegie
@SethCarnegie:复制“开关不创建新范围”的部分,我认为是错误的。6.8.4:“选择语句是一个块,其作用域是其封闭块的严格子集。”适用于ifswitch - undur_gongor
@undur_gongor 是的,非常抱歉,这个例子有误,现在已经更正了。我的意思是要表明每个 case 没有新的作用域。 - Seth Carnegie

2

因为int b;是一个声明,编译器不会为其生成代码。

int a = 1;

switch (a) {

/* Instructions corresponding to the code here will not be executed */
/* printf("hi"); Instructions for such code will never be executed */
/* int b;      It is just a declaration. No executable code is generated for it*/

int b = 34;/*Replaced int b by int b = 34 now b will never be initialized to 34*/
case 1:
   printf("%d",b);      /*you will get garbage value now*/
   break;
default:
   break;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接