我知道在所有C编译器实现背后都有一个标准,因此不应该有任何隐藏功能。尽管如此,我相信所有的C开发人员都有他们经常使用的隐藏/秘密技巧。
我知道在所有C编译器实现背后都有一个标准,因此不应该有任何隐藏功能。尽管如此,我相信所有的C开发人员都有他们经常使用的隐藏/秘密技巧。
C99有一些很棒的任意顺序结构初始化。
struct foo{
int x;
int y;
char* name;
};
void main(){
struct foo f = { .y = 23, .name = "awesome", .x = -38 };
}
匿名结构体和数组是我最喜欢的之一。(参见http://www.run.montefiore.ulg.ac.be/~martin/resources/kung-f00.html)
setsockopt(yourSocket, SOL_SOCKET, SO_REUSEADDR, (int[]){1}, sizeof(int));
或者void myFunction(type* values) {
while(*values) x=*values++;
}
myFunction((type[]){val1,val2,val3,val4,0});
它甚至可以用于实例化链表...
嗯……我认为C语言的一个强项是其可移植性和标准化,所以每当我在当前使用的实现中发现一些“隐藏技巧”时,我都尽量不使用它,因为我试图让我的C代码尽可能符合标准且具有可移植性。
当我第一次看到之后,这个(隐藏的)特性让我"震惊"的是printf。这个特性允许您在格式化格式说明符本身时使用变量。查看代码,您会更清楚:
#include <stdio.h>
int main() {
int a = 3;
float b = 6.412355;
printf("%.*f\n",a,b);
return 0;
}
*字符可以达到这种效果。
编译时断言,如此处已经讨论。
//--- size of static_assertion array is negative if condition is not met
#define STATIC_ASSERT(condition) \
typedef struct { \
char static_assertion[condition ? 1 : -1]; \
} static_assertion_t
//--- ensure structure fits in
STATIC_ASSERT(sizeof(mystruct_t) <= 4096);
字符串的常量拼接
我很惊讶地发现没有人提到这一点,因为我知道的所有编译器都支持它,但许多程序员似乎忽略了它。有时候它非常方便,不仅用于编写宏。
在我的当前代码中使用案例:
我在配置文件中有一个#define PATH "/some/path/"
(实际上是由makefile设置的)。现在我想要构建完整的路径,包括要打开资源的文件名。只需这样做:
fd = open(PATH "/file", flags);
不要用可怕但非常常见的方法:
char buffer[256];
snprintf(buffer, 256, "%s/file", PATH);
fd = open(buffer, flags);
注意到常见的可怕解决方案是:
\\
在多个源代码行上也是有用的。 - dolmen初始化数组或枚举时,可以在初始化列表中的最后一项后面加上逗号。例如:
int x[] = { 1, 2, 3, };
enum foo { bar, baz, boom, };
这样做是为了让你在自动生成代码时不需要担心去除最后一个逗号。
结构体赋值非常方便。很多人似乎没有意识到结构体也是一种值,可以进行赋值操作,不必使用memcpy()
函数,简单的赋值语句就能完成任务。
例如,考虑一个想象中的二维图形库,它可能定义了一个类型来表示(整数)屏幕坐标:
typedef struct {
int x;
int y;
} Point;
现在,您可能会做一些看起来“不对”的事情,比如编写一个从函数参数初始化点并返回它的函数,像这样:
Point point_new(int x, int y)
{
Point p;
p.x = x;
p.y = y;
return p;
}
只要使用结构体赋值将返回值按值复制,这样是安全的(当然):
Point origin;
origin = point_new(0, 0);
通过这种方式,您可以使用纯标准 C 编写相当干净和面向对象的代码。