C Programming

FreeBSD 的 strlen(3)

之前只有一篇关于较早版本的 strlen(3) 实现的笔记,这里补上我在 2010 年做的新增改进。

与 Pascal 等语言不同,C 的字符串并不保存串的长度,而是在字符串末尾以 nul 字符(’\0’)来表示字符串结束。这个设计决策是上世纪 60 年代作出的,有都市传说是为了省几个字节的空间,不过我个人认为也可能是因为汇编里面到处都是判断是否碰到了 0 的操作。不管怎么说,这个设计令 strlen 变成了一个 O(n) 的操作。

阅读全文…( 本文约 1364 字,阅读大致需要 3 分钟 )

一个奇怪的移位计算结果

今天 强迫症 朱小瘦同学提到一个非常有意思的问题,一个32bit的无符号整数算术右移32个bit应该得多少?

我们知道算术右移一个bit相当于除2,所以一个32bit无符号整数除以 2322^{32},理论上,应该得0。

然而事实不是这样。测试显示在 x86 系统上,一个32bit无符号整数算术右移32个bit之后得到的是原数。例如下面这个测试程序:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <stdio.h>

int
main(void /* int argc, char **argv */)
{
	unsigned int a = 0x5a5a5a5a;

	a >>= 32;

	printf("%x\n", a);

	return 0;
}

不启用任何优化的话,编译出来的程序得到的结果是:

5a5a5a5a

更进一步,我们将上面的测试改写为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <stdio.h>

int
main(void /* int argc, char **argv */)
{
	unsigned int a = 0x5a5a5a5a;
	int i;

	for (i=0; i<33; i++)
		printf("%x\n", a >> i);

	return 0;
}
阅读全文…( 本文约 881 字,阅读大致需要 2 分钟 )

sizeof(void *)和sizeof(int(*)(void))

以前一直没注意过这个问题,今天在邮件列表看到 Matthew Flemming 发的邮件才知道实际上 C 标准并不保证 sizeof(void *) == sizeof(int(*)(void))。不过,几乎所有的现代系统上这个等式都是成立的。

阅读全文…( 本文约 180 字,阅读大致需要 1 分钟 )