1 | if (表达式) |
1 | if (表达式) |
1 | switch (表达式) { |
1 |
|
break语句将导致程序的执行立即从switch语句中退出。在switch语句中,case的作用只是一个标号,因此,某个分支中的代码执行完后,除非使用break或return显式跳转,否则程序将进入下一个分支继续执行。
作为一种良好的程序设计风格,在switch语句最后一个分支(即default分支)的后面也加上一个break语句。这样做在逻辑上没有必要,但当我们需要向switch语句后添加其他分支时,这种防范措施会降低错误的可能性。
一个更通用的atoi例子,它可以处理可选的前导空白符以及一个可选的加+或减-号。
1 |
|
逗号运算符,是C语言优先级最低的运算符,在for语句中经常用到它。被逗号符分隔的一对表达式将按照从左到右的顺序进行求值。例如:reverse(s)函数,该函数用于倒置字符串s中各个字符的位置。
1 |
|
某些情况下的逗号并不是逗号运算符,比如分隔函数参数的逗号,分隔声明中变量的逗号等,这些逗号并不保证各表达式按从左到右的顺序求值。
应该慎用逗号运算符。逗号运算符最适用于关系紧密的结构中,比如上面的reverse函数内的for语句,对于需要在单个表达式中进行多步计算的宏来说也很适合。逗号表达式还适用于reverse函数中元素的交换,这样,元素的交换过程便可以看成是一个单步操作。
1 | for (i = 0, j = strlen(s)-1; i < j; i++, j--) |
C99规定了一种新的for循环语法,在控制表达式1的位置可以有变量定义。例如上例的循环变量i可以只在for循环中定义:
1 | int factorial(int n) |
如果这样定义,那么变量i只是for循环中的局部变量而不是整个函数的局部变量。在循环结束后就不能再使用i这个变量了。这个程序用gcc编译要加上选项-std=c99。这种语法也是从C++借鉴的,考虑到兼容性不建议使用这种写法。
示例:itoa函数(atoi函数的逆函数,把数字转换为字符串)
1 | /* itoa: convert n to characters in s */ |
break语句可以用于从for、while与do-while等循环中提前退出,就如同从switch语句中提前退出一样。break语句能使程序从switch语句或最内层循环中立即跳出。
下面的函数trim用于删除字符串尾部的空格符、制表符与换行符。当发现最右边的字符为非空格符、非制表符、非换行符时,就使用break语句从循环中退出。
1 | /* trim: remove trailing blanks, tabs, newlines */ |
continue语句用于使for、while或do-while语句开始下一次循环的执行。在while与do-while语句中,continue语句的执行意味着立即执行测试部分;在for循环中,则意味着使控制转移到递增循环变量部分。continue语句只用于循环语句,不用于switch语句。某个循环包含的switch语句中的continue语句,将导致进入下一次循环。
C语言提供了可随意滥用的goto语句以及标记跳转位置的标号。从理论上讲,goto语句是没有必要的,实践中不使用goto语句也可以很容易的写出代码。
但是,在某些场合下goto语句还是用得着的。最常见的做法是终止程序在某些深度嵌套的结构中的处理过程,例如一次跳出两层或多层循环。这种情况下使用break语句是不能达到目的的,它只能从最内层循环退出到上一级的循环。下面是使用goto的一个例子:
1 | for ( ... ) |
在该例子中,如果错误处理代码很重要,并且错误可能出现在多个地方,使用goto语句将会比较方便。
标号的命名同变量命名的形式相同,标号的后面要紧跟一个冒号。标号可以位于对应的goto语句所在函数的任何语句的前面。标号的作用域是整个函数。
我们来看另外一个例子。考虑判定两个数组a与b中是否具有相同元素的问题。一种可能的解决方法是:
1 | for (i = 0; i < n; i++) |
所有使用了goto语句的程序代码都能改写成不带goto语句的程序,但可能会增加一些额外的重复测试或变量。大多数情况下,使用goto语句的程序段比不使用goto语句的程序段要难以理解和维护,少数情况除外。因此,建议尽可能少的使用goto语句。