《再读》第二章 语法“陷阱”
2010-09-01 22:02
369 查看
看了第一章后发现第一节还是那么深奥啊~呵呵,今天看了第二章,虽然后点麻烦,不过
如果掌握了作者所说的关键的话,其实也不是特别难了,但还是有些声明的方法觉得很怪异,也
许是因为没有这样用过,也没听说过吧。今天难得的在书中找到了一些错误啊~呵呵,这算是一
个不大不小的收获吧。
1.对函数声明的理解。
在C语言中,声明分为两个部分:类型部分和一组类似表达式的声明符部分。声明符从表
面上来看与表达式有些类似,对它求值的话应该会返回一个声明中给定的类型的结果。一旦知道
了如何声明一个给定类型的变量,那么该类型的类型转换符就很容易得到了:只要不声明中的变
量和句末的分号去掉,然后用括号将之“封装”起来就行了。对于复杂的声明,我们只需要一层
一层的剖析,慢慢地就会知道其中的意思了。
2.运算符的优先级。
在C语言中,运算符是相当复杂的东西,不仅仅需要考虑优先级,还得考虑结合性,在这
一节中,作者为我们解决了优先级问题,同时,我也是在这一章发现的书中的错误。首先说说正
确的运算符的优先级顺序。
最高是:()(函数调用运算符)、[](下标运算符)、(->和.)(结构成员选择运算符)这四个运算符。
其次是:单目运算符。再次是算术运算符,其中 % * / 比 +
- 的优先级高。
再次是:移位运算符。再次是关系运算符,其中
< > <= >= 比
== != 的优先级高。
再次是:按位运算符,按位与的优先级高于按位或的优先级,按位异或的优先级在两者之间。
再次是:逻辑运算符。
再次是:条件运算符(唯一的三目运算符)。
再次是:赋值运算符(包括复合赋值运算符)。
最后是:逗号运算符
我们要记住两点:1.任何一个逻辑运算符的优先级低于任何一个关系运算符的优先级。2.移位
运算符的优先级比运算符低,但是比关系运算符高。
发现的错误:
在原书(中文版)中,优先级分成最高级的四个运算符,单目运算符和双目运算符三部分,
其中双目运算符又分为了算符运算符、位移运算符、关系运算符、逻辑运算符、赋值运算符、条
件运算符这几个依次降低的等级。而错误也就出现在这里,赋值运算符的真正的优先级应该比条
件运算符的低,这一点在后文中也有提到,而此处所说的是赋值运算符的优先级比条件运算符的
优先级高,这是我发现的书中的第一个错误(暂时),第二个错误是将条件运算符作为了二目元
算符,当然这一点译者也有指出,这个失误应该是原书作者的失误,至于第一个就不得而知了。
书中还提到“所有按位运算符的优先级要比顺序由运算符的优先级高,每个‘与’运算符的优先
级要比相应的‘或’运算符的优先级高,而按位异或运算符的优先级介于按位与运算符与按位或
运算符之间”。这个顺序运算符我不知道是单独指逗号运算符还是指&&、||、?:和,这四个运算符,
我暂时也没有查到,但看到网上有人将逗号运算符称作顺序求值运算符,但是根据我的理解和思
考,我个人认为指的是四种运算符,日后查到在做更改,如有知情者,可以留言或通过发邮件等
方式告诉我,谢谢合作。
3.注意作为语句结束标志的分号。
尤其要注意if、while、return、结构体的声明等语句。
4.Switch语句。
建议:每一个case语句后面都要记得加break;如果是特殊情况,需要将几句话共用的话要
写注释。default语句可有可无,可放置于任意位置,建议放置于最后,并且在末尾加一个break
语句,以防万一。
5.函数调用。
与某些语言不同,不论函数是否有参数,调用时都必须带有括号。例如:f();与f;f();是
函数的调用,而f;却什么也不做,说的更精确点是计算函数f的地址,并不调用该函数。
6.“悬垂”。
根据C语言的处理方式,else会与向上的第一个if配对,因此在进行if语句嵌套时往往
会引发“悬垂”的问题,即使是经验丰富的程序员也会犯这样的错误。例如下列代码:
if ( x == 0 )
if
( y == 0 )
err();
else {
z
= x + y;
f(&z);
}
这段代码的真正目的是先判断x是否等于0,如果是,则判断y是否等于0,如果是,则调用err
函数,不是,则什么也不干;如果x不等于0,则执行else的语句。但是由于“悬垂”问题导
致程序与编程者的意图大相径庭。整理代码:
if ( x == 0 )
if
( y == 0 )
err();
else
{
z
= x + y;
f(&z);
}
也就是说,这段代码真正实现的是先判断x是否等于0,是,则判断y是否等于0,是则执行err
函数,不是则执行else的语句,如果x不等于0则什么也不做。
建议,将if的语句用括号括起来,如下列代码:
if ( x == 0 ) {
if
( y == 0 )
err();
} else {
z
= x + y;
f(&z);
}
又或者进行一些宏定义,做一下处理:
#define IF { if {
#defien THEN } {
#define ELSE } else {
#defien FI } }
IF x == 0 THEN
IF
y == 0 THEN
err();
FI
ELSE
z
= x + y;
f(&z);
FI
这是第二章的内容。
如果掌握了作者所说的关键的话,其实也不是特别难了,但还是有些声明的方法觉得很怪异,也
许是因为没有这样用过,也没听说过吧。今天难得的在书中找到了一些错误啊~呵呵,这算是一
个不大不小的收获吧。
1.对函数声明的理解。
在C语言中,声明分为两个部分:类型部分和一组类似表达式的声明符部分。声明符从表
面上来看与表达式有些类似,对它求值的话应该会返回一个声明中给定的类型的结果。一旦知道
了如何声明一个给定类型的变量,那么该类型的类型转换符就很容易得到了:只要不声明中的变
量和句末的分号去掉,然后用括号将之“封装”起来就行了。对于复杂的声明,我们只需要一层
一层的剖析,慢慢地就会知道其中的意思了。
2.运算符的优先级。
在C语言中,运算符是相当复杂的东西,不仅仅需要考虑优先级,还得考虑结合性,在这
一节中,作者为我们解决了优先级问题,同时,我也是在这一章发现的书中的错误。首先说说正
确的运算符的优先级顺序。
最高是:()(函数调用运算符)、[](下标运算符)、(->和.)(结构成员选择运算符)这四个运算符。
其次是:单目运算符。再次是算术运算符,其中 % * / 比 +
- 的优先级高。
再次是:移位运算符。再次是关系运算符,其中
< > <= >= 比
== != 的优先级高。
再次是:按位运算符,按位与的优先级高于按位或的优先级,按位异或的优先级在两者之间。
再次是:逻辑运算符。
再次是:条件运算符(唯一的三目运算符)。
再次是:赋值运算符(包括复合赋值运算符)。
最后是:逗号运算符
我们要记住两点:1.任何一个逻辑运算符的优先级低于任何一个关系运算符的优先级。2.移位
运算符的优先级比运算符低,但是比关系运算符高。
发现的错误:
在原书(中文版)中,优先级分成最高级的四个运算符,单目运算符和双目运算符三部分,
其中双目运算符又分为了算符运算符、位移运算符、关系运算符、逻辑运算符、赋值运算符、条
件运算符这几个依次降低的等级。而错误也就出现在这里,赋值运算符的真正的优先级应该比条
件运算符的低,这一点在后文中也有提到,而此处所说的是赋值运算符的优先级比条件运算符的
优先级高,这是我发现的书中的第一个错误(暂时),第二个错误是将条件运算符作为了二目元
算符,当然这一点译者也有指出,这个失误应该是原书作者的失误,至于第一个就不得而知了。
书中还提到“所有按位运算符的优先级要比顺序由运算符的优先级高,每个‘与’运算符的优先
级要比相应的‘或’运算符的优先级高,而按位异或运算符的优先级介于按位与运算符与按位或
运算符之间”。这个顺序运算符我不知道是单独指逗号运算符还是指&&、||、?:和,这四个运算符,
我暂时也没有查到,但看到网上有人将逗号运算符称作顺序求值运算符,但是根据我的理解和思
考,我个人认为指的是四种运算符,日后查到在做更改,如有知情者,可以留言或通过发邮件等
方式告诉我,谢谢合作。
3.注意作为语句结束标志的分号。
尤其要注意if、while、return、结构体的声明等语句。
4.Switch语句。
建议:每一个case语句后面都要记得加break;如果是特殊情况,需要将几句话共用的话要
写注释。default语句可有可无,可放置于任意位置,建议放置于最后,并且在末尾加一个break
语句,以防万一。
5.函数调用。
与某些语言不同,不论函数是否有参数,调用时都必须带有括号。例如:f();与f;f();是
函数的调用,而f;却什么也不做,说的更精确点是计算函数f的地址,并不调用该函数。
6.“悬垂”。
根据C语言的处理方式,else会与向上的第一个if配对,因此在进行if语句嵌套时往往
会引发“悬垂”的问题,即使是经验丰富的程序员也会犯这样的错误。例如下列代码:
if ( x == 0 )
if
( y == 0 )
err();
else {
z
= x + y;
f(&z);
}
这段代码的真正目的是先判断x是否等于0,如果是,则判断y是否等于0,如果是,则调用err
函数,不是,则什么也不干;如果x不等于0,则执行else的语句。但是由于“悬垂”问题导
致程序与编程者的意图大相径庭。整理代码:
if ( x == 0 )
if
( y == 0 )
err();
else
{
z
= x + y;
f(&z);
}
也就是说,这段代码真正实现的是先判断x是否等于0,是,则判断y是否等于0,是则执行err
函数,不是则执行else的语句,如果x不等于0则什么也不做。
建议,将if的语句用括号括起来,如下列代码:
if ( x == 0 ) {
if
( y == 0 )
err();
} else {
z
= x + y;
f(&z);
}
又或者进行一些宏定义,做一下处理:
#define IF { if {
#defien THEN } {
#define ELSE } else {
#defien FI } }
IF x == 0 THEN
IF
y == 0 THEN
err();
FI
ELSE
z
= x + y;
f(&z);
FI
这是第二章的内容。
相关文章推荐
- 第二章语法陷阱
- 《c陷阱与缺陷》第二章,语法陷阱
- 《C陷阱与缺陷》 第二章 语法“陷阱”
- 第二章 语法“陷阱”
- c缺陷与陷阱笔记-第二章 语法陷阱
- 第二章 语法陷阱
- C陷阱与缺陷第二章 语法“陷阱”
- Kotlin Primer·第二章·基本语法
- Nvelocity 第二章 注释语法
- 第二章 高级语言及其语法描述
- Java私塾跟我学系列――JAVA篇 第二章 基础语法00
- 又犯了些小错误,bash语法陷阱真多
- JavaScript语法中12个需要绕开的陷阱
- JavaScript语法中的九个陷阱
- JavaScript第二章知识点总结——JavaScript的基本语法
- C++ FAQS 翻译3 (第一部分 预备知识 第二章 C++语法和语义基础)
- C_语法概念_sizeof 使用规则及陷阱分析
- C陷阱与缺陷之语法陷阱
- 再读《The C Programming Language》 第二章 2.1 变量类型
- 再读《The C Programming Language》 第二章 2.3 表达式