有谁知道switch语句是怎么样实现的? 说一下流程就可以了

wj_xiazi 2003-08-26 09:50:27
同上
...全文
128 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
tonybaobao 2003-08-26
  • 打赏
  • 举报
回复
实质就是if...else if...else if......else
out4b 2003-08-26
  • 打赏
  • 举报
回复
看不懂这段话:


“当然,编译器也可以使用“表机制”来实现switch-case,但据我所知还没有一个编译器是这样实现的。。“映射方式”的表驱动灵活性强,但运行效率不高。而索引方式的表驱动比switch-case高效已经是公认的事实了。”
out4b 2003-08-26
  • 打赏
  • 举报
回复
分支少的时候,比如只有两三个分支时用表驱动机制的速度可能不如条件跳转指令,并且会增加代码尺寸。当分支多的时候就是用表驱动了。特别地,对于以下这种判断连续的字符集中字符的switch-case,还存在另一种代码安排方式,它比单纯的表驱动效率高一些,因此,某些编译器(比如gcc)会评估switch-case中的开销然后决定生成什么样的代码:

switch(ch)
{
case 'a':
case 'b':
case 'c':
...
...
case 'z':
default:
}

Smartdoggie 2003-08-26
  • 打赏
  • 举报
回复
关于“分支少”时,这时用表驱动很慢吗?这里会成为效率瓶颈吗?应该这种情况下表驱动还是多分支对效率的影响已经不大了。而表驱动在可维护性方面的优势是多分支无法比拟的。多分支的唯一好处就是在语言直接支持下表现出来的编码简单容易,当语言直接支持表驱动的定义后它的这一仅存优势将不复存在。
wj_xiazi 2003-08-26
  • 打赏
  • 举报
回复
我看了汇编语句,好想是一堆if 语句。和每个case语句后的值比较,如果相等就跳转到相应的地址去。
Smartdoggie 2003-08-26
  • 打赏
  • 举报
回复
不知道谁才是对的
我也很困惑...
Smartdoggie 2003-08-26
  • 打赏
  • 举报
回复
http://expert.csdn.net/Expert/topic/2177/2177415.xml?temp=.8180506

关于switch-case与vtbl的效率比较并不这么简单,switch-case看起来是根据“开关变量”的值直接定位到所要执行的语句,但可惜的是,机器语言不支持这种结构,其最终实现其实就是很长的if-elseif结构。ajoo提到预取指令流的问题,switch-case对它的影响比vtbl机制还要大,因为它存在着多次条件跳转,并且都是“向前引用”。当然,编译器也可以使用“表机制”来实现switch-case,但据我所知还没有一个编译器是这样实现的。。“映射方式”的表驱动灵活性强,但运行效率不高。而索引方式的表驱动比switch-case高效已经是公认的事实了。
out4b 2003-08-26
  • 打赏
  • 举报
回复
我猜想可能把case后的一系列值做成一个表,然后用表达式的
值在这个表里查找。找到匹配的之后就知道了入口了。


你猜的是对的。对于分支不太多的情况,比如说少于10个,可以直接使用条件跳转指令实现。对于分支很多的情况可以用数组或hash表来实现,也就是类似于你说的这种方式。
cxjddd 2003-08-26
  • 打赏
  • 举报
回复
汇编里有种跳表技术。

我觉得它是先把所有的 case 值都判断完,确定从哪里开始,再跳过去执行。
wj_xiazi 2003-08-26
  • 打赏
  • 举报
回复
thanks!
但我想知道的是,怎么样找到入口的。我猜想可能把case后的一系列值做成一个表,然后用表达式的
值在这个表里查找。找到匹配的之后就知道了入口了。但我搭档不这样认为。
wxj797 2003-08-26
  • 打赏
  • 举报
回复
例:
char a;
int b;
cin>>a;
switch(a)
{
case 'r':b=1;
break;
case 'w':b=0;
break;
default:b=-1;
break;
}
cout<<b<<endl;
若某一case值与输入的switch表达式a相匹配,便以此case作为switch结构的入口,执行该case的语句,break使执行该语句后退出switch结构。
Smartdoggie 2003-08-26
  • 打赏
  • 举报
回复
一堆if
else if
out4b 2003-08-26
  • 打赏
  • 举报
回复
转一篇老帖子给大家看看:

From: ka@hropus.UUCP
Newsgroups: net.lang.c
Date: 4 Aug 86 20:37:41 GMT
Organization: Bell Labs, Holmdel, NJ

> As I understand it, a switch/case setup compiles exactly the same as
> if (var == const1) {.....};
> else if (var == const2) {.....};
> else {default_action};
> anyway.


A compiler should be able to do better than that. Generating good code for
switches is one place where compiler writers can show they know something
about searching.


Using a branch table will produce faster and smaller code if the cases
are consecutive integers. The only thing that may be non-obvious is the
best way to test whether the expression being switched on is within
range before accessing the branch table. A straightforward coding of
this test requires two comparisons, but Ritchie's compiler for the
PDP-11 generated only one comparison using the machine language
equivalent of the following code:


if ((unsigned)(value -= MIN) > (MAX - MIN) goto default;


On the PDP-11, this generates one less instruction (or two less, if MIN
is zero) than:


if (value < MIN || value > MAX) goto default;


(Learning hacks like these is one of the benefits of reading the
compiler.)


Since some people like to count starting at one, a possible enhancement
would be to change MIN from 1 to 0 in this case by adding an extra entry
to the beginning of the branch table. But real C programmer count from
0; wimps who count starting with 1 deserve to have their switch statements
execute slower. :-)


If the cases are not consecutive, the branch table must be filled with
entries for the "missing" cases, making the table larger. The Ritchie
compiler will generate a branch table if the number of entries in the
branch table would be less than three times the number of cases. If
the cases are mostly consecutive with a few outliers, a branch table
could be augmented with a few specific tests for the outliers, but I
don't know of any compiler that does this.


There are two general methods for implementing tables which do not rely
on the keys being nearly consecutive: hashing and the binary search.
Hashing, which is what the Ritchie compiler uses, has the advantage that
its performance is independent of the number of cases, just as with a
branch table. The modulo instruction is used as the hash function; the
C compiler tries a variety of values for the modulus and selects the
best one which means that the time required to generate the hash table
is proportional to the square of the number of cases.


The UN*X VAX compiler, on the other hand, uses a binary search. A
binary search executes in time proportional to the log of the number of
cases. This makes it sound worse that the hash search; I presume
someone discovered that most switch statements contained few enough
statements that the binary search was superior. The binary search works
best on a machine with a three way branch like that provided by the
Fortran arithmentic IF statement. On a machine with condition codes
like the VAX, each step of the binary search is implemented by a compare
instruction followed by two branches on the condition codes.


Several things may be done to improve the performance of the binary
search. First, many machines execute a conditional branch instruction
faster when no branch is taken, so that rather than testing the middle
value in the table one can test a value somewhat to one side in order to
decrease the chance that a branch will be taken. This is implemented in
the VAX compiler, but some other possible improvements are not. The
binary search could be abandoned in favor of the linear search at some
level (e. g. when the number of possibilities has been reduced to 2 or
3). If there are a series of consecutive cases, this can be used to
eliminate extra tests. (For example, if a number is known to be less
than 5 it cannot be greater than 4, and if a number is greater than 2 and
less than 4 then it must be equal to 3, but the VAX compiler will code
to test for both these cases.) Finally, each comparison generated by
the VAX compiler looks like:


cmpl r0,$7 # compare switch value with 7
beql L1 # if equal, branch to the code for case 7
bgtr L8 # if greater, branch to L8 for the next cmpl.
# The next cmpl instruction goes here.


Since the branch to L8 is more likely to be executed that the branch to
L1, the bgtr instruction should come first to minimize the number of
instructions executed.


For small cases, the good old linear search is used by both the Ritchie
and the VAX compilers. Several things are done to speed up the linear
search. First, the switch expression is copied into a register. This
helps in general but loses when the switch instruction is a register
variable or the switch contains only one case. (This is hard to fix
because the compilers generate the code for a switch in two pieces;
first they generate code to place the value to be switched on in r0, and
then they generate the code to implement the switch. Another problem
with this separation appears on the PDP-11, where it may be easier to
compute an expression in r1 than in r0 due to a brain damaged multiply
instruction.) Second, the compiler implements the search as a series of
compares followed by branch if equal instructions. This minimizes the
time required to reach the default case because in the default case none
of the branches will be taken. In contrast, the code at the top of this
article will probably be compiled into a series of branch if not equal
instructions, all of which will branch if there is no match.


The Ritchie compiler at one time actually generated a table of values
and labels, and did a linear search on it using a loop. This saves
space but takes more time. Furthermore, it doesn't even save space if
there are 1 or 2 cases. (The Ritchie compiler has special handling of
switch statements with no cases except the default.) The Ritchie
compiler was changed to generate linear searches using a series of
compare instructions quite a long time ago, but I don't know if Dennis
was responsible for the change.


I don't know why the VAX compiler uses with a linear search at all,
rather than using the binary search. Probably this was a holdover from
the Ritchie compiler, which must be prepared to generate a linear search
because a linear search will outperform a hash search on a few elements.


In general, then, a compiler should do pretty well by using a jump table
where possible and a binary search otherwise. What is actually optimum
must be determined by measuring various approaches on a specific machine.
Kenneth Almquist
ihnp4!houxm!hropus!ka (official name)
ihnp4!opus!ka (shorter path)
out4b 2003-08-26
  • 打赏
  • 举报
回复
没那么简单的,楼上的各位,你们测试的都是简单的情况。case条件很多的时候就不是这样了。
keiven 2003-08-26
  • 打赏
  • 举报
回复
就是很多的 if 和 else 语句啦!
wj_xiazi 2003-08-26
  • 打赏
  • 举报
回复
我看了汇编语句,好想是一堆if 语句。和每个case语句后的值比较,如果相等就跳转到相应的地址去。

69,364

社区成员

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

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