switch case 求助!!!

东方石头 2012-10-16 03:37:37
C程序设计 清大 第三版书上有一句话是这样的:
“case常量表达式”只是起语句标号的作用,并不是在该处进行条件判断。在执行switch语句时,根据switch后面表达式的值找到匹配的入口标示,就从此标示开始执行下去,不再进行判断。。。。。所以才用了break语句。
这句话改怎样理解?书上的例题我练过,但还是不太明白为什么这样写的原因呢。
希望各位大侠的帮助。。。
...全文
377 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
firendlys 2012-11-09
  • 打赏
  • 举报
回复
这个东西还是直接看汇编吧,简单易懂... 不需要什么高深汇编知识,看懂 jmp , cmp 这2条语句就够了. 有时候,类似这种基础语法,直接看汇编结果吧,简单直接明了(复杂的那些就不建议看汇编了)...

46:       int i=1;
00401048   mov         dword ptr [ebp-4],1
47:       int j=0;
0040104F   mov         dword ptr [ebp-8],0
48:       switch(i)//注意这里,整个switch只有在这里进行同一判断,然后直接跳转.
49:       {//这里有一大堆东西,具体意思不需要知道(毕竟现在不是在学汇编)
00401056   mov         eax,dword ptr [ebp-4]//只需要知道,整个switch里面所有case都是通过这堆代码
00401059   mov         dword ptr [ebp-0Ch],eax//进行跳转,就足够了.
0040105C   mov         ecx,dword ptr [ebp-0Ch]
0040105F   sub         ecx,1
00401062   mov         dword ptr [ebp-0Ch],ecx
00401065   cmp         dword ptr [ebp-0Ch],3
00401069   ja          $L7455+7 (00401095)
0040106B   mov         edx,dword ptr [ebp-0Ch]
0040106E   jmp         dword ptr [edx*4+4010A3h]
50:       case  1://在随后的这些case里面,实际上不需要在进行判断. 所以,这些case实际上只是一个标号的作用.
51:           j=1;//目的是为了在第一个case之前计算好每一个case需要跳转的地址.
00401075   mov         dword ptr [ebp-8],1
52:           break;//遇到 break 就直接跳转到 switch(){}大括号后面
0040107C   jmp         $L7455+0Eh (0040109c)
53:       case 2:
54:           j=2;
0040107E   mov         dword ptr [ebp-8],2
55:           break;
00401085   jmp         $L7455+0Eh (0040109c)
56:       case 3:
57:           j=3;//没有break的情况,就不会跳转出去,所以,程序就会继续执行,直到遇到break,或者
00401087   mov         dword ptr [ebp-8],3//执行到switch(){}大括号后面为止
58:       case 4:
59:           j=4;
0040108E   mov         dword ptr [ebp-8],4
60:       default:
61:           j=5;
00401095   mov         dword ptr [ebp-8],5
62:           break;
63:       }

//执行流程也该清楚了吧?
mymtom 2012-11-09
  • 打赏
  • 举报
回复
引用 4 楼 zhuankeshumo 的回复:
这种情况是C的缺点 C#里面必须加break; 不然报错
不是缺点,是特点。不然也不会有 Duff's device
SKATE11 2012-11-09
  • 打赏
  • 举报
回复
意思是先找到对应的case处 然后向后执行 如果后面没有遇到退出语句的话 就会一直执行下去
lin5161678 2012-11-09
  • 打赏
  • 举报
回复
引用 4 楼 zhuankeshumo 的回复:
这种情况是C的缺点 C#里面必须加break; 不然报错
C#的处理还不如C 如果必须加 那么干脆处理完一个case后直接退出
gaochizhen33 2012-11-09
  • 打赏
  • 举报
回复
引用 12 楼 gaochizhen33 的回复:
引用 11 楼 summybloom 的回复:引用 8 楼 zhao4zhong1 的回复:VC调试时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断……
我看错楼主的困惑了。。。 没有break的话会逐一执行剩下的case,break的作用就是执行完一个case后跳出switch中。
gaochizhen33 2012-11-09
  • 打赏
  • 举报
回复
引用 11 楼 summybloom 的回复:
引用 8 楼 zhao4zhong1 的回复:VC调试时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Tur……
这是赵老师的专用回复。 switch和case之间的语句将不会被执行,匹配到case后将直接跳到相应的case中。

switch(x){
int a = 2;
case 1:printf("1");
    break;
case 2:printf("2");
    break;
}
在这个语句中int a = 2将不会被执行,如何在case中使用了变量a,是会报错的。
东方石头 2012-11-08
  • 打赏
  • 举报
回复
引用 8 楼 zhao4zhong1 的回复:
VC调试时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo De……
我试了一下您说的快捷按键,但是没反应呢?我用的VC6.0 是不是这个快捷键和你说的那个不一样啊? 像这种快捷键从哪里看? 我还是初学者 一下方面不懂 请见谅!
L_chxu 2012-10-16
  • 打赏
  • 举报
回复
简单的说,当你用switch语句判断的时候,程序跳到符合条件的那个Case进入执行,

“只是起语句标号的作用,并不是在该处进行条件判断”

这句话的意思是,case作标记用,符合条件时的入口。不是进行判断的原因是:当它进入这个入口后,如果下面的case语句后面没有break;语句,它仍然会进去执行。(如果它是进行条件判断,那么下面的肯定不符合条件,就不会进去了,而事实上它执行了,就说明不是判断的)
proorck6 2012-10-16
  • 打赏
  • 举报
回复
这样说是为了和if-else区分开来
如果是

switch(x){
case 1:printf("1");
case 2:printf("2");
}
将显示两个数
这样设计是为了实现如下的代码

switch(x){
case 1:case 2:
printf("1 or 2");
case 3:case 4:
printf("3 or 4");
}
赵4老师 2012-10-16
  • 打赏
  • 举报
回复
VC调试时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
xiaoxiao8310 2012-10-16
  • 打赏
  • 举报
回复
“case常量表达式”只是起语句标号的作用 个人觉得可以理解为goto语句的标号一样

...........
goto end;
..........
end:
printf("end\n");

whizered 2012-10-16
  • 打赏
  • 举报
回复
根据switch后面的值,在case里面找到对应的项,然后从这个case开始顺序执行,遇到break跳出switch.如果没有遇到break,则一直执行完毕,所以为了只执行一个case语句,往往会在其后加break.但是也有不加break的情况,那么就会顺序向下执行.
mymtom 2012-10-16
  • 打赏
  • 举报
回复
[code=C/C++]
#include <stdio.h>

int main(int argc, char *argv[])
{
int c;

c = argc;

switch (c) {
case 3:
printf("%s@%d\t: c=%d\n", __FILE__, __LINE__, c);
case 2:
printf("%s@%d\t: c=%d\n", __FILE__, __LINE__, c);
case 1:
printf("%s@%d\t: c=%d\n", __FILE__, __LINE__, c);
default:
c = -1;
break;
}

return 0;
}
[/Code]
newtee 2012-10-16
  • 打赏
  • 举报
回复
这种情况是C的缺点
C#里面必须加break; 不然报错
newtee 2012-10-16
  • 打赏
  • 举报
回复
case后面的常量表达式实际上只起语句标号作用,而不起条件判断作用,即"只是开始执行处的入口标号". 因此,一旦与switch后面圆括号中表达式的值匹配,就从此标号处开始执行,而且执行完一个case后面的语句后,若没遇到break语句,就自动进入 下一个case继续执行,而不在判断是否与之匹配,直到遇到break语句才停止执行,退出break语句.因此,若想执行一个case分之后立即跳出 switch语句,就必须在此分支的最后添加一个break语句.
newtee 2012-10-16
  • 打赏
  • 举报
回复
#include <stdio.h>

int main()
{
char x = 'B';
switch (x){
case 'A':printf("A");
case 'B':printf("B");
case 'C':printf("C");
default: printf("D");
}
}
result: BCD

case后面的常量表达式实际上只起语句标号作用,而不起条件判断作用,即"只是开始执行处的入口标号". 因此,一旦与switch后面圆括号中表达式的值匹配,就从此标号处开始执行,而且执行完一个case后面的语句后,若没遇到break语句,就自动进入 下一个case继续执行,而不在判断是否与之匹配,直到遇到break语句才停止执行,退出break语句.因此,若想执行一个case分之后立即跳出 switch语句,就必须在此分支的最后添加一个break语句.
  • 打赏
  • 举报
回复
switch后面的值是几,就在case里面找到对应的项,执行,跳出,每次进入switch,只执行其中的一个case
按下矩阵按键在数码管上逐个显示对应的键值,键值如下: S1-S4:0-3 S4-S8:4-7 S9-S12:8-B S13-S16:C-F */ #include #define GPIO_DIG P0 #define GPIO_KEY P1 sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; unsigned char code DIG_CODE[17]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码 unsigned char KeyValue; //用来存放读取到的键值 unsigned char KeyState; //记录按键的状态,0没有,1有 unsigned char DisplayData[8]; //用来存放要显示的8位数的值 void Delay10ms(); //延时10ms void KeyDown(); //检测按键函数 void DigDisplay(); //动态显示函数 /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main(void) { KeyState=0; while(1) { KeyDown(); if(KeyState==1) { DisplayData[7]=DisplayData[6]; DisplayData[6]=DisplayData[5]; DisplayData[5]=DisplayData[4]; DisplayData[4]=DisplayData[3]; DisplayData[3]=DisplayData[2]; DisplayData[2]=DisplayData[1]; DisplayData[1]=DisplayData[0]; DisplayData[0]=DIG_CODE[KeyValue]; KeyState=0; } DigDisplay(); } } /******************************************************************************* * 函 数 名 : DigDisplay * 函数功能 : 使用数码管显示 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void DigDisplay() { unsigned char i; unsigned int j; for(i=0;i<8;i++) { switch(i) //位选,选择点亮的数码管, { case(0): LSA=0;LSB=0;LSC=0; break;//显示第0位 case(1): LSA=1;LSB=0;LSC=0; break;//显示第1位 case(2): LSA=0;LSB=1;LSC=0; break;//显示第2位 case(3): LSA=1;LSB=1;LSC=0; break;//显示第3位 case(4): LSA=0;LSB=0;LSC=1; break;//显示第4位 case(5): LSA=1;LSB=0;LSC=1; break;//显示第5位 case(6): LSA=0;LSB=1;LSC=1; break;//显示第6位 case(7): LSA=1;LSB=1;LSC=1; break;//显示第7位 } GPIO_DIG=DisplayData[i];//发送段码 j=10; //扫描间隔时间设定 while(j--); GPIO_DIG=0x00;//消隐 } } /******************************************************************************* * 函 数 名 : KeyDown * 函数功能 : 检测有按键按下并读取键值 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void KeyDown(void) { unsigned int a=0; GPIO_KEY=0x0f; if(GPIO_KEY!=0x0f) { Delay10ms(); a++; a=0; if(GPIO_KEY!=0x0f) { KeyState=1;//有按键按下 //测试列 GPIO_KEY=0X0F; // Delay10ms(); switch(GPIO_KEY) { case(0X07): KeyValue=0;break; case(0X0b): KeyValue=1;break; case(0X0d): KeyValue=2;break; case(0X0e): KeyValue=3;break; // default: KeyValue=17; //检测出错回复17意思是把数码管全灭掉。 } //测试行 GPIO_KEY=0XF0; Delay10ms(); switch(GPIO_KEY) { case(0X70): KeyValue=KeyValue;break; case(0Xb0): KeyValue=KeyValue+4;break; case(0Xd0): KeyValue=KeyValue+8;break; case(0Xe0): KeyValue=KeyValue+12;break; // default: KeyValue=17; } while((a<500)&&(GPIO_KEY!=0xf0)) //按键松手检测 { Delay10ms(); a++; } a=0; } } } /******************************************************************************* * 函 数 名 : Delay10ms * 函数功能 : 延时函数,延时10ms * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void Delay10ms(void) //误差 0us { unsigned char a,b,c; for(c=1;c>0;c--) for(b=38;b>0;b--) for(a=130;a>0;a--); }

70,022

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧