有些C语言语法比较生僻,且有其他常规方式替代,建议尽量避开这些装x的写法,少折腾自己,也少折磨别人。下面是个人主观感觉,仅供参考。原则是简单比复杂好。
数组作函数参数
数组作为函数的参数传递时,会退化成一个地址,也就是说你写的是数组array[],编译器把它作为地址&array处理,既然如此不如直接写&array清楚而明确。
结构体直接赋值
struct TEST{
…
int * pbuf;
}test;
test a, b;
a.pbuf =malloc(100);
b=a;
……
free(a.pbuf);
alg(b.pbuf); //错误,访问野指针
例中b=a结构体赋值等价于memcpy(&b,&a,sizeof(test)),属于浅拷贝,即b=a时只是b.pbuf=a.pbuf,而并不会新申请一块内存给b.pbuf。那当释放掉a.pbuf后,b.pbuf就变成野指针。相比直接memcpy或者逐个成员赋值,b=a因为形式的简洁反而把这个浅拷贝的危险隐藏得更深。所以不要显摆你懂得结构体=号赋值了,老老实实memcpy吧。
结构体做参数和返回值
结构体相比数组地位高不少,它可以作为函数参数和返回值,且作函数参数时是不退化的值传递,会一个不少把结构体成员全部传进函数。相对只传一个地址值的结构体指针,结构体整体传递对时间和空间消耗都较大(函数传参通过寄存器和栈空间,这二者都是稀缺资源)。并且值传递是单向,如果函数内部改变结构体成员的值,该值不能返回主调函数。
无论从那个角度,结构体指针或引用做参数都好过结构体变量亲自赤膊上阵,一旦出现,多数说明程序员概念不清,不会使用指针。
define中的#和##
两个符号都只能出现在define宏定义中,#是把宏参数变为一个字符串,##是把两个宏参数连接在一起。说起这两个家伙就是一把心酸泪,通常阅读C代码都是基于符号查找函数/类型/变量的定义和实现,从而理解程序流程,可一旦#和##掺和进来,符号名就有可能动态组合生成,导致根本搜索不到函数/类型/变量的定义,一片哀号。
虽然包括linux kernel等一些经典开源代码里有不少这种写法,我还是固执的认为除非某些场景必须动态产生符号,否则不要刻意用#和##去生成。综合效率可读性等因素,一些笨拙的实现未必比那些看似高级的写法差。
变量复用
int i , a;
for(i=0;i<100;i++) {......}
a = ......
当a和i的作用域独立不重叠时,有人认为去掉变量a而复用i代替会更紧凑和高效,因为这种复用看似能减少变量数目。但由于编译器完全能够统筹安排变量背后对堆栈、寄存器等资源的占用,也就是说变量数目和资源占用在源码级别并不对应,编译器不会因此领情。实际上刻意用一个变量复用多个逻辑含义只会降低代码可读性。