找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7256|回复: 3
打印 上一主题 下一主题
收起左侧

break、continue和goto语句在C语言中的区别和用法

[复制链接]
跳转到指定楼层
楼主
ID:109770 发表于 2016-3-22 23:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
<break语句>
break语句通常用在循环语句和开关语句中。当break用于开关语句switch中
时, 可使程序跳出switch而执行switch以后的语句; 如果没有break语句, 则将
成为一个死循环而无法退出。
当break语句用于do-while、for、while循环语句中时, 可使程序终止循环
而执行循环后面的语句, 通常break语句总是与if语句联在一起。 即满足条件时
便跳出循环。
例:
main()
{
int i=0;
char c;
while(1)                 /*设置循环*/
{
c='\0';             /*变量赋初值*/
while(c!=13&&c!=27) /*键盘接收字符直到按回车或Esc键*/
{
c=getch();
printf("%c\n", c);
}
if(c==27)
break;          /*判断若按Esc键则退出循环*/
i++;
printf("The No. is %d\n", i);
}
printf("The end");
}
注意:
1. break语句对if-else的条件语句不起作用。
2. 在多层循环中, 一个break语句只向外跳一层。
<continue 语句>
continue语句的作用是跳过本循环中剩余的语句而强行执行下一次循环。
continue语句只用在for、while、do-while等循环体中, 常与if条件语句一
起使用, 用来加速循环。
例:
main()
{
char c;
while(c!=0X0D)      /*不是回车符则循环*/
{
c=getch();
if(c==0X1B)
continue; /*若按Esc键不输出便进行下次循环*/
printf("%c\n", c);
}
}
<goto 语句>
goto语句是一种无条件转移语句, 与BASIC中的goto语句相似。goto 语句的
使用格式为:
goto 标号;
其中标号是Turbo C2.0中一个有效的标识符, 这个标识符加上一个":" 一起
出现在函数内某处, 执行goto语句后, 程序将跳转到该标号处并执行其后的语句。
另外标号必须与goto语句同处于一个函数中, 但可以不在一个循环层中。通常
goto语句与if条件语句连用, 当满足某一条件时, 程序跳到标号处运行。
goto语句通常不用, 主要因为它将使程序层次不清, 且不易读, 但在多层嵌
套退出时, 用goto语句则比较合理。
例:
main()
{
int i=0;
char c;
while(1)
{
c='\0';
while(c!=13)
{
c=getch();
if(c==27)
goto quit;
printf("%c\n", c);
}
i++;
printf("The No. is %d\n", i);
}
quit:
printf("The end");
}



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:109770 发表于 2016-3-22 23:21 | 只看该作者
goto语句
goto语句的发展历程
  问题起源:
  60年代中期以后,计算机硬件技术日益进步,计算的存贮容量、运算速度和可靠性明显提高,生产硬件的成本不断降低。计算机价格的下跌为它的广泛应用创造了极好的条件。在这种形势下,迫切要求计算机软件也能与之相适应。因而,一些开发大型软件系统的要求提了出来。然而软件技术的进步一直未能满足形势发展的需要,在大型软件的开发过程中出现了复杂程度高、研制周期长、正确性难以保证的三大难题。遇到的问题找不到解决办法,致使问题堆积起来,形成了人们难以控制的局面,出现了所谓的“软件危机”。为了克服这一危机,一方面需要对程序设计方法、程序的正确性和软件的可靠性等问题进行系列的研究;另一方面,也需要对软件的编制、测试、维护和管理的方法进行研究,从而产生了程序设计方法学。
  goto语句是有害的观点:
  1968年,E·W·代克斯特拉首先提出“GOTO语句是有害的”论点,向传统程序设计方法提出了挑战,从而引起了人们对程序设计方法讨论的普遍重视。
  goto语句的争论:
  在60年代末和70年代初,关于GOTO语句的用法的争论比较激烈。主张从高级程序语言中去掉GOTO语句的人认为,GOTO语句是对程序结构影响最大的一种有害的语句,他们的主要理由是:GOTO语句使程序的静态结构和动态结构不一致,从而使程序难以理解,难以查错。去掉GOTO语句后,可直接从程序结构上反映程序运行的过程。这样,不仅使程序结构清晰,便于理解,便于查错,而且也有利于程序的正确性证明。
  持反对意见的人认为,GOTO语句使用起来比较灵活,而且有些情形能提高程序的效率。若完全删去GOTO语句,有些情形反而会使程序过于复杂,增加一些不必要的计算量。
  关于goto语句的解决方法:
  1974年,D·E·克努斯对于GOTO语句争论作了全面公正的评述,其基本观点是:不加限制地使用GOTO语句,特别是使用往回跳的GOTO语句,会使程序结构难于理解,在这种情形,应尽量避免使用GOTO语句。但在另外一些情况下,为了提高程序的效率,同时又不致于破坏程序的良好结构,有控制地使用一些GOTO语句也是必要的。用他的话来说就是:“在有些情形,我主张删掉GOTO语句;在另外一些情形,则主张引进GOTO语句。”从此,使这场长达10年之久的争论得以平息。
  后来,G·加科皮尼和C·波姆从理论上证明了:任何程序都可以用顺序、分支和重复结构表示出来。这个结论表明,从高级程序语言中去掉GOTO语句并不影响高级程序语言的编程能力,而且编写的程序的结构更加清晰。
  goto语句的结果:
  在C/C++等高级编程语言中保留了goto语句,但被建议不用或少用。在一些更新的高级编程语言,如Java不提供goto语句,它虽然指定goto作为关键字,但不支持它的使 用,使程序简洁易读;尽管如此后来的c#还是支持goto语句的,goto语句一个好处就是可以保证chengx程序存在唯一的出口,避免了过于庞大的if嵌套。
回复

使用道具 举报

板凳
ID:109770 发表于 2016-3-22 23:22 | 只看该作者
goto语句在C/C++语言中可谓是“臭名昭著”,乃至有的书(或公司的编程规范)提出禁用goto语句的说法。其结果就是,造成有的程序员一看到goto语句在某程序中被使用,就本能地认为这个程序写得很“垃圾”。此外,也使得有些程序员因为使用了goto语句而觉得自己很不专业。其实,凡事都不能太偏激,goto语句运用得好能大大地简化程序,以及提高程序的可读性和可维护性。在开始示例其好处之前,先用一些统计数据来说明goto语句并没有因为“臭名昭著”而被抛弃,这些统计数据可能并不是百分之百的精确,但很具有说服力。对于操作系统,Linux-2.6.21内核使用了20,333个goto语句,VxWorks-6.2则使用了9142个,最后941个goto语句被运用到了rtems-4.9.2中;另外,glibc-2.9库使用了1750个goto语句。所有这些统计数据都表明,goto语言并没有想象的那样可怕而招到禁用,其关键在于 —— 恰当地运用它。

图1是一个没有采用goto语句编写的函数,其中存在多处出错处理的代码,比如113~115行、120~122行和126~129行。采用这种分布式的出错处理,很容易出现遗漏释放前面已经分配的资源,从而造成资源泄漏问题。如果采用goto语句,则能取得更好的效果。

example.c
00097: int queue_init (queue_t ** _pp_queue, int _size)
00098: {
00099:     pthread_mutexattr_t attr;
00100:     queue_t *queue;
00101:
00102:        queue = (queue_t *) malloc(sizeof(queue_t));
00103:        if (0 == queue) {
00104:         return -1;
00105:     }
00106:     *_pp_queue = queue;
00107:
00108:     memset (queue, 0, sizeof (*queue));
00109:     queue->size_ = _size;
00110:
00111:     pthread_mutexattr_init (&attr);
00112:     if (0 != pthread_mutex_init(&queue->mutex_, &attr)) {
00113:         pthread_mutexattr_destroy (&attr);
00114:         free (queue);
00115:         return -1;
00116:     }
00117:
00118:     queue->messages_ = (void **) malloc (queue->size_ * sizeof (void *));
00119:     if (0 == queue->messages_) {
00120:         pthread_mutexattr_destroy (&attr);
00121:         free (queue);
00122:         return -1;
00123:     }
00124:
00125:     if (0 != sem_init(&queue->sem_put_, 0, queue->size_)) {
00126:         free (queue->messages_);
00127:         pthread_mutexattr_destroy (&attr);
00128:         free (queue);
00129:         return -1;
00130:     }
00131:
00132:     pthread_mutexattr_destroy (&attr);
00133:
00134:     return 0;
00135: }


图1

图2是采用goto语句所编写的另一个版本,与不采用goto语句的版本相比,程序更加的简单,且在出错处理的地方大都使用goto语句跳转到程序的末尾进行处理。goto语句除了可以用在这里所示例的出错处理中,还可以用在其它的程序逻辑中以简化程序并提高阅读性。
example.c
00053: int queue_init (queue_t ** _pp_queue, int _size)
00054: {
00055:     pthread_mutexattr_t attr;
00056:     queue_t *queue;
00057:
00058:     queue = (queue_t *) malloc(sizeof(queue_t));
00059:         if (0 == queue) {
00060:         return -1;
00061:     }
00062:     *_pp_queue = queue;
00063:
00064:     memset (queue, 0, sizeof (*queue));
00065:     queue->size_ = _size;
00066:
00067:     pthread_mutexattr_init (&attr);
00068:     if (0 != pthread_mutex_init(&queue->mutex_, &attr)) {
00069:         goto error;
00070:     }
00071:
00072:     queue->messages_ = (void **) malloc (queue->size_ * sizeof (void *));
00073:     if (0 == queue->messages_) {
00074:         goto error;
00075:     }
00076:
00077:     if (0 != sem_init(&queue->sem_put_, 0, queue->size_)) {
00078:         goto error1;
00079:     }
00080:
00081:     pthread_mutexattr_destroy (&attr);
00082:
00083:     return 0;
00084:
00085: error1:
00086:     free (queue->messages_);
00087: error:
00088:     pthread_mutexattr_destroy (&attr);
00089:     free (queue);
00090:     return -1;
00091: }


图2

使用goto语句时需要注意以下原则:
1) 不要过份地使用。比如图2中的60行就没有采用goto语句跳到程序的最后面,之所以这里不使用goto是为了阅读方便。因为程序此时还没有分配资源,所以直接返回显得更加的直接了当。还有就是,在这个函数中如果存在使用goto语句都意味着出错了且需要释放资源。如果将60行的语句也改为goto就破坏了这个函数中使用goto语句的一致性。
2) 不要让goto语句形成一个环。使用goto语句应形成一条线,从一点跳到另一点。当然,如果goto语句的使用没有破坏可读性,那可以适当的考虑打破这一原则。


回复

使用道具 举报

地板
ID:109770 发表于 2016-3-22 23:25 | 只看该作者
在中断中使用goto语句:LZ用汇编写过程序,就应该明白
当你进入中断服务程序时,单片机本身会备份当前程序状态,中断部分执行完毕后会用RETI恢复现场
如果这时候主程序是在执行一个子程序时进入的中断,那么中断执行完毕后自然会继续执行之前的子程序毫无影响,问题就在这...中断部分用LJMP之类跳转指令(相当于goto),自然是“合法”得跳转到目的地,但之前被执行到一半的子程序将会被彻底打断,程序架构一旦没处理好这部分,出问题也在所难免,比如一个状态机,在状态改变时的那一步被打断......
这样的话,要么你在所有不可打断处关闭中断,处理完毕后再打开,但这样程序可移植性等等都将被破坏
要么用类似如下主循环:
while(1)
{
    工作1;
        跳转变量检测;
    工作2;
        跳转变量检测;
    工作3;
        跳转变量检测;
    工作4;
        跳转变量检测;
    ....
}
这样看似语句啰嗦不少,但每次大循环也就牺牲若干个微秒便可保证响应的速度



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表