我知道在所有C编译器实现背后都有一个标准,因此不应该有任何隐藏功能。尽管如此,我相信所有的C开发人员都有他们经常使用的隐藏/秘密技巧。
我知道在所有C编译器实现背后都有一个标准,因此不应该有任何隐藏功能。尽管如此,我相信所有的C开发人员都有他们经常使用的隐藏/秘密技巧。
并不是真正的隐藏功能,但第一次看到像这样的东西时,它让我感觉像巫术:
void callback(const char *msg, void *data)
{
// do something with msg, e.g.
printf("%s\n", msg);
return;
data = NULL;
}
将变量与字面值进行比较时,最好将字面值放在==运算符的左侧,以确保当您错误地使用赋值运算符时编译器会发出错误提示。
if (0 == count) {
...
}
一开始看起来可能有些奇怪,但它可以避免一些麻烦(比如如果你不小心打成if (count = 0)
)。
if (count = 0)
时会生成警告,使其有些多余。 - Mark Ransom摘要:
在这个页面上,您将找到一些有趣的C编程问题/谜题列表。这些程序是我从朋友的电子邮件转发中收到的,也有一些是我在书籍中读到的,还有一些是我从互联网上获取的,以及一些是我在C编程经验中获得的。
我曾经使用register
关键字声明一些变量以加快速度。这会提示C编译器将CPU寄存器用作本地存储。现代C编译器自动执行此操作,因此这很可能不再必要。
函数指针的大小不是标准的。至少在K&R书中没有。尽管它谈论了其他类型指针的大小,但(我认为)sizeof
函数指针是未定义行为。
sizeof
也是一个编译时运算符,我看到很多人在在线论坛上问sizeof
是函数还是运算符。
我见过的一个错误如下(一个简化的例子):
int j;
int i;
j = sizeof(i++)
i
的增量不会被执行,因为 sizeof
在编译时被计算。程序员打算在一个语句中同时修改 i
的增量和 sizeof
的计算。
C 中的运算符优先级控制的是结合顺序而不是计算顺序。例如,如果你有三个函数 f
、g
、h
,每个函数都返回一个 int
,并且有一个表达式如下:
f() + g() * h()
C标准没有规定这些函数的评估顺序。在将g
和h
的结果相乘之前,将添加f
的结果。如果这些函数共享状态并且计算依赖于这些函数的评估顺序,则可能会导致错误。这可能会导致可移植性问题。
假设你有一个成员都是同一类型的结构体:
struct Point {
float x;
float y;
float z;
};
您可以将其实例转换为浮点指针并使用数组索引:
Point a;
int sum = 0, i = 0;
for( ; i < 3; i++)
sum += ((float*)a)[i];
虽然很基础,但在编写简洁代码时非常有用。
这里有三个在gcc中不错的:
__FILE__
__FUNCTION__
__LINE__
在 switch 语句中使用 while(0),这样你就可以像使用 break 语句一样使用 continue 语句,怎么样?
void sw(int s)
{
switch (s) while (0) {
case 0:
printf("zero\n");
continue;
case 1:
printf("one\n");
continue;
default:
printf("something else\n");
continue;
}
}
变长结构体,在常见的解析器库等地方看到。
struct foo { int a; int b; char b[1]; // 使用 [0] 不再正确 // 必须放在最后 };
char *str = "abcdef"; int len = strlen(str); struct foo *bar = malloc(sizeof(foo) + len);
strcpy(bar.b, str); // 尝试阻止我吧!
char b [];
这种方式有一个优点,你不需要减去结构体体积中 1*sizeof b[0]
的大小。 - Patrick Schlüter我刚读了这篇文章。它涉及到一些 C 语言和其他几种编程语言的“隐藏特性”。