來自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
看完這個因該可以明白它的調用順序了吧。具體編譯器如何運作的,還需要高人來解釋:)