C语言的奇技淫巧

C语言

的tricks不多,但大多比较晦涩,就跟数学一样需要循序渐进的理解,同时也需要对编译器、C语言标准都有一定的理解。而C语言的雷区较多,也即有很多我们经常碰到的未定义行为(undefined behavior)。在看tricks前,我们先看个雷:

它看起来很简单,对吗?但如果b和c加起来大于了上限,如INT_MAX,那编译器会做什么?事实上这里会得到一个负数。这是非常令人烦躁的未定义举动,尤其是你因为它而要debug的时候。当然,标准会告诉你每次都去检查它没有意义,我们要的只是一个高速语言。恩,读者要记住一件事,玩标准的人不写代码。而且,千万不要轻易的忽略它们,它们都有可能造成致命的问题。——所以说C语言是高手才能真正玩好的语言。如果没有对C语言较好的了解,不要轻易的使用各类tricks,说不定里面就埋了个debug不出来的雷。

我们开始,先看个小技巧,舒缓一下心情:

编译器判断优化

这个技巧就是在循环判断时去期望是或否。这涉及到了编译器优化,以及很经典的火车选路。在linux内核中十分常见。你可以给知道它的人加5分,懂一点内核挺好的。

定长类型

再来一个我们在强类型时不能忽略的:

这些类型非常棒,比起char, short, int, long的意思清晰十倍,尤其在bitmap运算时,最好用这些强类型(记得在算bits时要用UINT)。

但你可以看到项目组里往往用

这样的代码来定义它们,实际上是错误的,乖乖的#include 为好。

逗号运算符

像这样用是可以的。注意逗号取最后一个值返回。

结构体初始化

注意它不是一般意义上的全0初始化,而是逻辑0初始化,这里引用一段stackoverflow上的英文:

memset/calloc do “all bytes zero” (i.e. physical zeroes), which is indeed not defined for all types. { 0 } is guaranteed to intilaize everything with proper logical zero values. Pointers, for example, are guranteed to get their proper null values, even if the null-value on the given platform is 0xBAADFOOD

Bit fields

很有用的bit定义,尤其是用在某些算法中

 有限自动机

that can be achieved with the following macros:

Interlacing structures

Interlacing structures like Duff’s Device:

数组指定初始化技巧

很好用的技巧,GCC早期已经实现,后合入C99,但其他很多编译器没有实现

同上:

GCC-参数格式化

 动态指定浮动打印精度

静态检查

编译时而非运行时

字符串连接

0 bit fields

which will give a layout of

instead of without the :0;

The 0 width field tells that the following bitfields should be set on the next atomic entity (char)

Lambda

Lambda’s (e.g. anonymous functions) in GCC:

This can be used as:

Which is expanded into:

字符选择

include/宏 协助数组初始化-预编译技巧

打印调用点技巧,适合跟踪调试代码

强悍而需要功力的X_MACRO


你可能感兴趣的:(C)