《C陷阱与缺陷》读书笔记2

 

第二章   语法陷阱 

 

2.1  理解函数声明

 

        任何C变量的声明都由两部分组成:类型以及一组类似表达式的声明符(declarator)。

 

        float *g(), (*h)();

        表示*g()与(*h)()是浮点表达式。因为()结合优先级高于*,*g()也就是*(g()):g是一个函数,该函数的返回值类型为指向浮点数的指针。同理,可以得出h是一个函数指针,h所指向函数的返回值为浮点类型。

 

        给定类型的类型转换符,只需要把声明中的变量名和声明末尾的分号去掉,再将剩余的部分用一个括号整个“封装”起来即可。例如,下面的声明:

        float (*h)();

        表示h是一个指向返回值为浮点类型的函数的指针,因此,

        ( float (*) () )

        表示一个“指向返回值为浮点类型的函数的指针”的类型转换符。

 

        ( *(void(*)())0)() : 调用首地址为0位置的子例程

        void(*)() : 一个指向返回值为void类型的函数的指针

        (void(*)())0 : 将常数0转型为“指向返回值为void的函数的指针”类型

 

2.2  运算符的优先级问题

 

        FLAG是一个整数,且该整数值的二进制表示中只有某一位是1,其余各位均为0。

        flags也是一个整型变量,需要判断它在常量FLAG为1的那位上是否同样为1。

        if ( flags & FLAG )

        为了使可读性更好,显示判断表达式的值是否为0,写法如下:

        if ( flags & FLAG != 0 )

        虽然更好懂了,却是一个错误的语句。因为!=的优先级高于&,上式等价于

        if ( flags & ( FLAG != 0 ) )

 

        hi 和 low是两个整数,值介于0到15之间,如果r是一个8位整数,且r的低4位与low各位商的数一致,而r的高4位与hi各位上的数一致。写成如下:

        r = hi << 4 + low ;

        但是很不幸,这样写是错误的。加分运算的优先级比移位运算的优先级高,因此,本例实际上相当于:

        r = hi << ( 4 + low );

        更正方法1:加括号  r = ( hi <<4 ) + low;

        更正方法2:将加号改为按位逻辑或  r = hi << 4 | low; //这种方法牵涉到移位与逻辑运算的优先级,就更加不明显了。

 

        优先级最高者其实并不是真正意义上的运算符,包括:数组下表、函数调用操作符各结构成员选择操作符。它们都是自左于右,因此a.b.c的含义是( a.b ).c,而不是a.( b.c )

        单目运算符仅次于上面所述运算符。在所有的真正意义上的运算符中,它们的优先级最高。因为函数调用的优先级高于单目运算符的优先级,所以,如果p是一个函数指针,要调用p所指向的函数,必须这样写:( *p )()。 如果写成 *p() 编译器会理解成 *( p() )。类型转换也是单目运算符,它的优先级和其他单目运算符的优先级一样。单目运算符是自右至左,因此 *p++ 会被编译器解释成 *(p++),即取指向p所指向的对象,然后将p递增1;而不是(*p)++,即取指针p所指向的对象,然后将该对象递增1。

        优先级比单目运算符要低的,接下来是双目运算符。在双目运算符中,算术运算符的优先级最高,移位运算符次之,关系运算符再次之,接着是逻辑运算符,条件运算符,最后是赋值运算符。

       

        ==和!= 的优先级要低于其他关系运算符。因此如果要比较a与b的相对大小顺序是否和c与d的相对大小顺序一样,可以这样写: a < b == c < d

 

        ^按位异或运算符

 

        while ( c = getc ( in ) != EOF )

            putc ( c, out );

        等价于 while ( c = ( getc ( in ) != EOF ) )

 

 

2.3 注意作为语句结束标志的分号

 

2.4  switch语句

 

2.5  函数调用

        如果f 是一个函数,f(); 是一个函数调用语句,而 f; 却是一个什么也不做的语句。更精确地说,这个语句计算函数f的地址,却不调用该函数。

 

2.6  悬挂else引发的问题

        Else始终与同一对括号内最近的未匹配的if结合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值