【Deep C (and C++)】深入理解C/C++(2)(二)

2014-11-24 12:34:46 · 作者: · 浏览: 1
te_t,并不总是与int类型一样。因此,printf中的输出格式%d,不是一个很好的说明符。

你:好。那么,应该使用什么格式说明符?

候选者:这有点复杂。site_t是一个无符号整型数,在32位机器上,它通常是一个无符号的int类型的数,但是在64位机器上,它通常是一个无符号的long类型的数。然而,在C99中,针对site_t类型,指定了一个新的说明符,所以,%zu会是一个不多的选择。

你:好。那我们先完善这个说明符的bug。你接着回答这个问题吧。


#include

struct X
{
int a;
char b;
int c;
};

int main(void)
{
printf("%zu\n", sizeof(int));
printf("%zu\n", sizeof(char));
printf("%zu\n", sizeof(struct X));
}

候选者:这取决与平台,以及编译时的选项。唯一可以确定的是,sizeof(char)是1.你要假设在64位机器上运行吗?
你:是的。我有一台64位的机器,运行在32位兼容模式下。

候选者:那么由于字节对齐的原因,我觉得答案应该是4,1,12.当然,这也取决于你的编译选项参数,它可能是4,1,9.如果你在使用gcc编译的时候,加上-fpack-struct,来明确要求编译器压缩struct的话。

你:在我的机器上确实得到了4,1,12。为什么是12呢?

候选者:工作在字节不对齐的情况下,代价非常昂贵。因此编译器会优化数据的存放,使得每一个数据域都以字边界开始存放。struct的存放也会考虑字节对齐的情况。

你:为什么工作在字节不对齐的情况下,代价会很昂贵?

候选者:大多数处理器的指令集都在从内存到cpu拷贝一个字长的数据方面做了优化。如果你需要改变一个横跨字边界的值,你需要读取两个字,屏蔽掉其他值,然后改变再写回。可能慢了10不止。记住,C语言很注意运行速度。

你:如果我得struct上加一个char d,会怎么样?

候选者:如果你把char d加在struct的后面,我预计sizeof(struct X)会是16.因为,如果你得到一个长度为13字节的结构体,貌似不是一个很有效的长度。但是,如果你把char d加在char b的后面,那么12会是一个更为合理的答案。

你:为什么编译器不重排结构体中的数据顺序,以便更好的优化内存使用和运行速度

候选者:确实有一些语言这样做了,但是C/C++没有这样做。

你:如果我在结构体的后面加上char *d,会怎么样?

候选者:你刚才说你的运行时环境是64位,因此一个指针的长度的8个字节。也许struct的长度是20?但是另一种可能是,64位的指针需要在在效率上对齐,因此,代码可能会输出4,1,24?

你:不错。我不关心在我的机器上会得到什么结果,但是我喜欢你的观点以及洞察力J

(未完待续)

静候

摘自 Rockics的专栏