【问题标题】:How does switch statement work?switch 语句是如何工作的?
【发布时间】:2012-03-13 14:50:26
【问题描述】:

如何处理 switch-case 块中任何 case 标记语句之前的语句。 请解释以下程序的行为

程序1:

#include<stdio.h>
int main()
{
  switch(1)
  {   
    int i=0; 
    case 1:printf("%d",i);         
  }
getchar();
return 0;
}

输出:垃圾值。

程序2:

#include<stdio.h>
int main()
{
  switch(1)
  {  
    printf("Inside Switch");  
    case 1:printf("Case 1\n");      
  }
  printf("Outside Switch");
  getchar();
  return 0;
}

输出:

案例一

外部开关。

根据程序 2,标记为 case 的语句之前的语句似乎无法访问,但是为什么我在第一个程序中没有收到未声明变量 i 的错误(仅警告)。

如果有人能详细解释switch 语句在内部是如何处理的,那将非常有帮助。

【问题讨论】:

  • 这是作业吗?这听起来像家庭作业。如果是这样,请添加homework 标签并展示您迄今为止的工作。
  • @T.J.Crowder 这不是家庭作业。我在参加 gild 的 C 测验时遇到了这个问题,我很想知道。
  • switch 语句基本上是带有gotos 的跳转表的语法糖。
  • 您是否尝试过使用相同的编译器在 switch 范围之外编译未声明变量的使用?它输出什么?也许这取决于编译器的警告/错误设置?在这里:cprogramming.com/tutorial/lesson5.html
  • @TheNail 我确实尝试过。但它给出了一条错误消息。

标签: c switch-statement


【解决方案1】:

引用 c 标准可以很好地解释这一点。 我在这里引用了适用于您的问题的标准的相关部分。

6.8.4.2 switch 语句

第 4 段:

switch 语句导致控制跳转到、进入或跳过作为 switch 正文,取决于控制表达式的值,以及是否存在 default 标签和任何case 标签的值在开关体上或开关体中......

第 2 段:

如果 switch 语句在 具有可变修改类型的标识符,整个 switch 语句应在 该标识符的范围。154)

脚注:

154) 也就是说,声明要么在 switch 语句之前,要么在与包含声明的块中的 switch 关联的最后一个 casedefault 标签之后.

第 7 段:
示例在人工程序片段中

switch (expr)
{
    int i = 4;
    f(i);
    case 0:
       i = 17;
       /* falls through into default code */
    default:
       printf("%d\n", i);
}

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


上述内容适用于问题中的两个代码示例。
Example 1i 具有 Indeterminate 值,因为它从未被初始化并因此打印垃圾,而在
Example 2, printf 调用未到达,因为控件跳转到匹配的case 标签。

【讨论】:

  • 感谢您为我回答的这个问题和其他问题。非常感谢。
  • +1。如果您有兴趣,我还有一篇关于编译器如何实现它们的小文章,请参阅here
【解决方案2】:

基本上,switch 的作用就像是转到相应的标签——中间的语句不会被执行。变量定义(实际上发生在编译时)确实会发生,但如果它们包含初始化,也会被跳过。

【讨论】:

    【解决方案3】:

    切勿在 switch 中编写不属于任何情况或默认值的语句,因为它们不会被执行。

    注意:可以在那里写声明,但不能写声明(int i; 是声明,但 int i = 10; 是声明 + 赋值 = 声明,所以赋值不会在那里执行..!)

    switch(a)
    {
    printf("This will never print"); // this will never executed
    case 1:
            printf(" 1");
    break;
     
    default :
    break;
    }
    

    【讨论】:

    • 感谢您的链接和回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多