《C 陷阱与缺陷》

词法

===

这句恐怕不用说什么,就已经可以触动很多人内心最痛的点了。。。

&, &&; |, ||

也是区分近似符号。

二元运算符两边要有空格

C编译时对符号的解析使用贪心法,取合法的最长的符号进行解析。因此当二元运算符与一一元运算符之间太过紧密的话,编译器有时不会领悟编程者的“深刻意图”。
a---b写成a - --ba-- - b 是截然不同的效果。还有x/*p,表示的意义应该是x / *p,而不是x /* p

字符串

char str[] = "qwerty";

执行这句后,sizeof ( str )strlen( str )的结果相差为1

语法

声明形式与类型转换

已知变量的声明形式,则只需把声明中的变量名和末尾分号去掉,然后把剩下的部分用括号括括起来,就是该类型的强制类型转换符号。
void (*fp)( int );表示fp是一个指向参数为整数,返回值为空的一个函数的指针。则( void ( * )( int ) ) new_fp即可将new_fp转换成为fp所表示的那种函数。

switchcasebreak

想必这个与第一条一样,是很多人心中永远的痛。。。所以当一个case刻意不使用break时,一定要用注释标明;否则每个case都就有一个break

语义

数组名

对于以下两个变量

char  a[ 10 ];
char *b = ( char * ) malloc( 10 );

不考虑ab生存期,只考虑仅变量名时其代表的含义,那么除了sizeof ( a )sizeof ( b )中两者有明显差别外,其他情况下ab都代表的是其所指向的一列元素中首个元素的地址。

求值顺序

C语言有四个运算符存在规定的求值顺序,分别是&&||?:,
&&||先对左侧操作数求值,只在需要时才对右侧操作数求值。
a?b:c先对a求值,然后根据需要对bc进行求值。
,先对左侧操作数求值,然后该值被“丢弃”,再对右侧操作数求值,最终返回最右操作数结果。

补充:

  1. 函数参数中的参数计算顺序是从右向左的。
  2. 对于++--
    • x++ + x++这样的计算中,先用x本来的值计算完整个算式并完成赋值后,再根据++的数目对x进行计算;
    • a = x++, b = x++这样的计算中,分句中++的效果类似于a = x++; b = x++;,顺序为从左向右计算;
    • func( x++, x++ )这样的函数调用中,参数从右向左进行计算,每个参数计算完成后先对x进行自加,然后计算左边的参数。

预处理器

带参数的宏

带参数的宏在定义时,宏名与参数括号间绝对不能出现空格。

宏定义中的括号

宏实现中,应当在必要时加入圆括号或花括号对宏实现进行包裹。如:

#define bigger( a, b )    ( ( a ) > ( b ) ? ( a ) : ( b ) )

#define max( ret, b, c )  \
  do {                    \
    if ( (b) > (c) ) {    \
      ret = (b);          \
    } else {              \
      ret = (c);          \
    }                     \
  } while ( 0 )

宏的参数

由于宏只是简单的替换,因此不要在使用宏时让宏携带可变参数,如x++等,以免出现意想不要的结果。

嵌套宏

宏尽量不要嵌套使用,尤其不能嵌套多层。否则宏被展开后将会成为非常复杂的式子。

暂无评论
  1. 蜗牛哥哥 蜗牛哥哥

    xxx喜欢了这篇文章
    表情good job

添加新评论