变量在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输出。