来自csdn的一个问题:问题如下:
〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉〉
请问那位高手能指明为什么while语句下的switch语句会执行和当i等于2时case 1:printf("i=%d,",i);语句又不执行了。希望能
将代码中while和switch将明白些
main()
{
int i,j;
printf("...../n");
for(i=0;i<3;i++)
{
j=3;
switch(i)
{
case 0:
while(j)
{
case 1:printf("i=%d,",i);
case 2:printf("j=%d,",j);j--;
default:;
}
}printf("...../n");
}
}
〈〈〈〈〈〈〈〈〈〈〈〈〈〈〈〈〈〈〈〈
下面是俺的回答,记录一下自己第一次使用汇编分析C代码:)
先看这个程序的输出:
//-----switch1.c----
int main()
{
int i=2;
switch(i)
{
case 0:
printf("case 0");
case 1:
printf("case 1");
case 2:
printf("case 2");
case 3:
printf("case 3");
default:
printf("case default");
}
getchar();
}
//OUTPUT:
case 2case 3 case default
说明了没有break的时候,如果switch找到了匹配的项,它将一直继续下去直到break或者switch终止。
于是我们回头看源程序:
//----------switch.c---------
main()
{
int i,j;
printf("...../n");
for(i=0;i<3;i++)
{
j=3;
switch(i)
{
case 0:
while(j)
{
case 1:printf("i=%d,",i);
case 2:printf("j=%d,",j);j--;
default:;
}
}printf("...../n");
}
getchar();
}
这里的for循环中i没有变化,所以i的值分别为 0 ,1,2
当i=0时进入for循环内部后:
case 0 匹配,所以后面的所有case都将被执行(因为没有break)
于是进入while循环:j进行递减直到=0。于是输出:i=0,j=3,i=0,j=2,i=0,j=1,.......
下一次循环i=1,此时case 0 不能匹配,但是进入while循环中的 case 1匹配了,于是输出类似于上面:
i=1,j=3,i=1,j=2,i=1,j=1,.......
i=2时,先匹配到的是case 2.于是输出为j=3,i=2,j=2,i=2,j=1,.......
为了更清楚地明白while在switch中的作用,我们精简了一下代码
//-switch.c---
main()
{
int i=1,j=3;
switch(i)
{
case 0:
while(j)
{
case 1:printf("i=%d,",i);
case 2:printf("j=%d,",j);j--;
default:;
}
}
}
下面是汇编码:
.file "switch.c"
gcc2_compiled.:
___gnu_compiled_c:
.def ___main; .scl 2; .type 32; .endef
.text
LC0:
.ascii "i=%d,/0"
LC1:
.ascii "j=%d,/0"
.align 4
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp,%ebp
subl $24,%esp
call ___main
movl $1,-4(%ebp) ;这两句为i和j赋值 i为-4(%ebp) j为-8(%ebp)
movl $3,-8(%ebp)
movl -4(%ebp),%eax ;i到eax
cmpl $1,%eax ;i和1比较
je L8 ;相等跳到L8
cmpl $1,%eax ;i和1比较
jg L12 ;大于跳到L12
testl %eax,%eax ;执行testl %eax,%eax可以用于判断eax中是否为零
je L4 ;是零跳到L4
jmp L10 ;while 循环
.p2align 4,,7
L12: ;case 2
cmpl $2,%eax
je L9
jmp L10
.p2align 4,,7
L4:
nop
.p2align 4,,7
L5:
cmpl $0,-8(%ebp) ;while 条件
jne L8
jmp L3
.p2align 4,,7
L7:
L8: ;L8为case 1 中执行的语句
addl $-8,%esp
movl -4(%ebp),%eax
pushl %eax
pushl $LC0
call _printf
addl $16,%esp
L9: ;L9为case 2中执行的语句
addl $-8,%esp
movl -8(%ebp),%eax
pushl %eax
pushl $LC1
call _printf
addl $16,%esp
decl -8(%ebp)
L10:
jmp L5
.p2align 4,,7
L6:
L3:
L2:
leave
ret
.def _printf; .scl 2; .type 32; .endef
看完这个因该可以明白它的调用顺序了吧。具体编译器如何运作的,还需要高人来解释:)