C语言goto,longjmp()和setjmp()之间有什么区别
goto语句实现程序执行中的近程跳转(local jump),longjmp()和setjmp()函数实现程序执行中的远程跳转(nonlocaljump,也叫farjump)。通常你应该避免任何形式的执行中跳转,因为在程序中使用goto语句或longjmp()函数不是一种好的编程习惯。goto语句会跳过程序中的一段代码并转到一个预先指定的位置。为了使用goto语句,你要预先指定一个有标号的位置作为跳转位置,这个位置必须与goto语句在同一个函数内。在不同的函数之间是无法实现goto跳转的。
下面是一个使用goto语句的例子:
void bad_programmers_function(void)
{
int x
printf("Excuse me while I count to 5000... \n") ;
x----l~
while (1)
{
printf(" %d\n", x)
if (x ==5000)
goto all_done
else
x=x+1;
}
all_done:
prinft("Whew! That wasn't so bad, was it?\n");
}
如果不使用goto语句,是例可以编写得更好。下面就是一个改进了实现的例子:
void better_function (void)
{
int x
printf("Excuse me while I count to 5000... \n");
for (x=1; x<=5000, x++)
printf(" %d\n", x)
printf("Whew! That wasn't so bad, was it?\n") ;
}
前面已经提到,longjmp()和setjmp()函数实现程序执行中的远程跳转。当你在程序中调用setjmp()时,程序当前状态将被保存到一个jmp_buf类型的结构中。
此后,你可以通过调用longjmp()函数恢复到调用setjmp()时的程序状态。与goto语句不同,longjmp()和setjmp()函数实现的跳转不一定在同一个函数内。然而,使用这两个函数有一个很大的缺陷,当程序恢复到它原来所保存的状态时,它将失去对所有在longjmp()和setjmp()之间动态分配的内存的控制,也就是说这将浪费所有在longjmp()和setjmp()之间用malloc()和calloc()分配所得的内存,从而使程序的效率大大降低。
因此,你应该尽量避免使用longjmp()和setjmp()函数,它们和goto语句一样,都是不良编程习惯的表现。
下面是使用longjmp()函数和setjmp()函数的一个例子:
#include <stdio.h>
#include <setjmp.h>
jmp_buf saved_state;
void main(void);
void call_ longjmp (void);
void main(void)
{
int ret_code;
printf("The current state of the program is being saved... \n");
ret_code = setjmp (saved_state)
if (ret_code ==1)
{
printf("The longjmp function has been called. \n" )
printf("The program's previous state has been restored. \n");
exit(0)
}
printf("I am about to call longjmp and\n");
printf('return to the previous program state... \n" )
call_ longjmp ( )
}
void call_longjmp (void)
{
longjmp (saved_state, 1 )
}
switch语句的最后一个分支可以不要break语句吗
尽管switch语句的最后一个分支不一定需要break语句,但最好还是在switch语句的每个分支后面加上break语句,包括最后一个分支。这样做的主要原因是:你的程序很可能要让另一个人来维护,他可能要增加一些新的分支,但没有注意到最后一个分支没有break语句,结果使原来的最后一个分支受到其后新增分支的干扰而失效。在每个分支后面加上break语句将防止发生这种错误并增强程序的安全性。
此外,目前大多数优化编译程序都会忽略最后一条break语句,所以加入这条语句不会影响程序的性能。
请参见:
1、什么时候用一条switch语句比用多条if语句更好?
2、switch语句必须包含default分支吗?
C语言switch语句必须包含default分支吗
不!但是为了进行错误检查或逻辑检查,还是应该在switch语句中加入default分支。例如,下述switch语句完全合法:
switch (char_code)
{
case tyt:
case 'y': printf ( " You answered YES ! \n" )
break
case 'N':
case 'n': printf ("You answered NO!\n");
break
}
但是,如果一个未知字符被传递给这条switch语句,会出现什么情况呢?这时,程序将没有任何输出。因此,最好还是加入一个default分支,以处理这种情况:
......
default: printf ("Unknown response : %d\n", char_code);
break
......
此外,default分支能给逻辑检查带来很多方便。例如,如果用switch语句来处理数目固定的条件,而且认为这些条件之外的值都属于逻辑错误,那么可以加入一个default分支来辨识逻辑错误。
请看下列:
void move_cursor (int direction)
{
switch (direction)
{
case UP: cursor_up()
break
case DOWN: cursor_down()
break
case LEFT: cursor_left ()
break
case RIGHT: cursor_ right ( )
break
default: printf ("Logic error on line number %ld!!! \n",
__ LINE__ )
break
}
}
请参见:
1、什么时候用一条switch语句比用多条if语句更好?
2、Switch语句的最后一个分支可以不要break语句吗?
C语言编程中,什么时候用一条switch语句比用多条if语句更好
如果你有两个以上基于同一个数字(numeric)型变量的条件表达式,那么最好使用一条switch语句。例如,与其使用下述代码:
if (x ==l)
printf ("x is equal to one. \n");
else if (x ==2)
printf ("x is equal to two. \n");
else if (x = =3)
printf ("x is equal to three. \n");
else
printf ("x is not equal to one, two, or three. \n");
不如使用下述代码,它更易于阅读和维护:
switch (x)
{
case 1: printf ("x is equal to one. \n");
break;
case 2: printf ("x is equal to two. \n");
break
case 3: printf ('x is equal to three. \n");
break;
default: printf ("x is not equal to one, two, or three. \n");
break;
}
注意:使用switch语句的前提是条件表达式必须基于同一个数字型变量。例如,尽管下述if语句包含两个以上的条件,但该例不能使用switch语句,因为该例基于字符串比较,而不是数字比较:
char *name="Lupto";
if(!stricmp(name,"Isaac"))
printf("Your name means'Laughter'.\n");
else if(!stricmp(name,"Amy"))
printf("Your name means'Beloved'.\n");
else if(!stricmp(name,"Lloyd"))
printf("Your name means'Mysterious'.\n");
else
printf("I haven't a clue as to what your name means.\n");
请参见:
1、switch语句必须包含default分支吗7
2、switch语句的最后一个分支可以不要break语句吗?