栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

C陷阱与缺陷 第2章 词法“陷阱” 2.3 注意作为语句结束标注的分号

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C陷阱与缺陷 第2章 词法“陷阱” 2.3 注意作为语句结束标注的分号

注意作为语句结束标志的分号
在C语言中,如果不小心多写了一个分号,可能不会造成什么不良后果:这个分号也许会被视为一个不会产生任何实际效果的空语句;或者编译器会因为这个多余的分号而产生一个警告语句,根据警告信息的提示能够很容易去掉这个分号。
一种重要的例外情况时在if或者while语句之后需要紧跟一条语句时,如果多写了一个分号,那么原来紧跟在if或者while子句之后的语句就是一条单独的语句,与条件判断部分没有了任何关系。 
if (x[i] > big);
    big = x[i];
编译器会正常地接受第一行代码中的分号而不会提示任何警示信息。这个例子实际上相当于: 
if (x[i] > big) {
}
    big = x[i];
当然,也就等同于(除非x、i或者big是有副作用的宏)
big = x[i]; 
编译器对这段程序代码的处理与对下面这段代码的处理就大不相同: 
if (x[i] > big) {
    big = x[i];
}
如果不是多写了一个分号,而是遗漏了一个分号,同样会招致麻烦,例如: 
if (n < 3) 
    return
logrec.date = x[0];
logrec.time = x[1];
logrec.code = x[2];
此处的return语句遗漏了一个分号,然而这段程序仍然会顺利通过编译而不会报错,只是将语句
logrec.date = x[0];
当做了return语句的操作数。上面这段程序代码实际上相当于: 
if (n < 3) {
    return logrec.date = x[0];
} 
logrec.time = x[1];
logrec.code = x[2];
如果这段代码所在的函数声明其返回值为void,编译器会因为实际返回值的类型跟声明返回值的类型不一致而报错。然而,如果一个函数不需要返回值(即返回值为void),我们通常会在函数声明时省略返回值类型,但是此时对编译器而言会隐含地将函数返回值类型视为int类型。如果是这样,上面的错误就不会被编译器检测到。在上面的例子中,当n>=3时,第一个赋值语句被直接跳过,由此造成的错误可能会是一个潜伏很深,极难发现的程序Bug。

当一个声明的结尾紧跟一个函数定义时,有分号与没分号的实际效果相差极为不同。如果声明结尾的分号被省略,编译器可能会把声明的类型视作函数的返回值类型。考虑下面的例子: 
struct logrec {
    int date;
    int time;
    int code;
} main() { //main is a function name, return type of function
//is struct logrec.
    ...
}
在第一个}与紧随其后的函数main定义之间,遗漏了一个分号。因此,上面代码段的实际效果是声明函数main的返回值是struct logrec类型。写成下面这样会看得更清楚: 
struct logrec {
    int date;
    int time;
    int code;
}
main() {
    ...
}
如果分号没有被省略,函数main的返回值类型会缺省定义为int类型。

虽然刻意地往消极面去联想也许有些“病态”,但对于要考虑到各种意外情况的程序设计来说(比如航空航天或医疗仪器的控制程序),却是不无裨益的。
 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1021641.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号