词法
=
与 ==
这句恐怕不用说什么,就已经可以触动很多人内心最痛的点了。。。
&
, &&
; |
, ||
也是区分近似符号。
二元运算符两边要有空格
C
编译时对符号的解析使用贪心法
,取合法的最长的符号进行解析。因此当二元运算符与一一元运算符之间太过紧密的话,编译器有时不会领悟编程者的“深刻意图”。
如a---b
写成a - --b
和a-- - 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
所表示的那种函数。
switch
的case
的break
想必这个与第一条一样,是很多人心中永远的痛。。。所以当一个case
刻意不使用break
时,一定要用注释标明;否则每个case
都就有一个break
。
语义
数组名
对于以下两个变量
char a[ 10 ];
char *b = ( char * ) malloc( 10 );
不考虑a
和b
生存期,只考虑仅变量名时其代表的含义,那么除了sizeof ( a )
和sizeof ( b )
中两者有明显差别外,其他情况下a
和b
都代表的是其所指向的一列元素中首个元素的地址。
求值顺序
C
语言有四个运算符存在规定的求值顺序,分别是&&
,||
,?:
和,
。
&&
和||
先对左侧操作数求值,只在需要时才对右侧操作数求值。
a?b:c
先对a
求值,然后根据需要对b
或c
进行求值。
,
先对左侧操作数求值,然后该值被“丢弃”,再对右侧操作数求值,最终返回最右操作数结果。
补充:
- 函数参数中的参数计算顺序是从右向左的。
- 对于
++
和--
:- 在
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++
等,以免出现意想不要的结果。
嵌套宏
宏尽量不要嵌套使用,尤其不能嵌套多层。否则宏被展开后将会成为非常复杂的式子。
xxx喜欢了这篇文章
表情good job