变量在switch语句中声明和初始化

为什么这个程序不输出20?

#include int main() { int a = 1; switch (a) { int b = 20; case 1: { printf("b is %d\n", b); break; } default: { printf("b is %d\n", b); break; } } return 0; } 

因为switch语句跳转到相关的case,所以int b = 20的行永远不会被执行。

您的编译器应该警告您。 ‘b’的初始化位于switch语句的开头,它永远不会被执行 – 执行将始终直接从switch语句标题流到匹配的case标签。

它不输出“b = 20”,因为b在switch语句中设置,并且从不执​​行该指令。 你想要的是这个:

 int b = 20; switch (a) { case 1: { printf("b is %d\n", b); break; } default: { printf("b is %d\n", b); break; } } 

当你调用printf()时,Gcc会发出警告,说b是未初始化的

你必须在switch()之前移动“int b = 20”

在开关内部是隐藏的goto语句。 所以基本上发生的事情真的是

 int a=1; if(a==1){ //case 1 goto case1; }else{ //default goto default; } int b=20; case1:.... 

代码

 int b = 20 

实际上做了两件事:

 int b 

 b = 20 

编译器在编译程序时设置一个名为b的变量。 这是一个automatic变量,它在堆栈上。 但是在程序执行到达该点之前,它不会为其赋值。

在此之前,不知道变量的值是多少。

对于全局变量或static变量,这不是真的 – 那些在程序开始运行时被初始化。

请记住, switch语句中的case标签被称为“标签”有一个原因:它们几乎是普通的标签,就像你可以goto标签一样。 这实际上就是switch工作方式:它只是goto的结构化版本,它只是从switch跳转到相应的标签并从那里继续执行。 在你的代码中,你总是跳过b初始化。 所以, b永远不会被初始化。

使用gcc进行编译(在Windows上使用cygwin)会发出警告信息 –

警告: switch语句 开头 无法访问的代码

并且输出是未定义的或垃圾,这清楚地表明b的初始化部分从未被执行,因此未定义的值。

注意:如果代码或行无法访问,可以提出问题,那么为什么我们不会收到错误:’b’未声明。

编译器检查程序的语法(上面检查是否声明了b)并发现它是正确的(b被声明),尽管在语义/逻辑上它是不正确的。

可能在将来,编译器可能变得更加智能,并且能够检测到这些错误

这条线

int b=20;

在进入开关之前不执行。 你必须将它移到switch语句之上才能获得20输出。