探讨C关键字sizeof
2013-04-11 13:09
176 查看
structnode{inta;intb;};
问:sizeof(Node)是多少?答案很简单,在32位机器上,一个int是4个字节,两个int就是8个字节,sizeof(Node)就是8。
好的,上面那个答案确实是8,那么再看下面这个结构体:
structnode{chara;intb;};
问:这个时候sizeof(Node)又是多少呢?int是4个字节,char是1个字节,答案是5?
这回,没有那么幸运,经过在机器上的操作,答案是8! Why?
实际上,这不是语言的问题,你在ANSI C中找不到为什么会这样!甚至你在不同的体系结构、不同的编译器下会得到不同的答案。那么,到底是谁把5改成了8呢?
这就引入了一个概念,叫做“内存对齐”。所谓的内存对齐,是指一种计算机体系结构(如X86)对基本数据类型的存储位置有限制,要求其地址为某个数 的倍数,通常这个数为4或8。这种要求会简化处理器的设计以及提升数据访问的效率。至于为什么会有这样的设计,简单的说访存总线的位数固定,以32位总线 为例,地址总线的地址总是4对齐的,所以数据也四对齐的话,一个周期内就可以把数据读出。这里不理解的话可以跳过去,只要记得对齐这回事儿就行了。如果想 更深入的理解,可以看这里另一篇文章。
知道这个之后,那么我们就可以理解,实际上是编译器为了效率,在相邻的变量之间放置了一些填充字节来保证数据的对齐。X86结构是4对齐的,所以sizeof(Node)是8不是5。
再来看一个例子:
structnode{inta;charb;charc;intd;chard;};
这时的sizeof(Node)是多少呢?没错,是16。
好的,既然我们知道对齐是由编译器来作的,那么我们可不可以更改对齐数呢?答案是可以的,在C语言中,我们可以通过
#pragma pack(n)
来更改对齐模数。
注:以上都是在现x86 linux下使用gcc编译器验证,不乏有其他系统和编译器会得到不同的结果。
再让我们来看个例子:
structnode{doublea;intb;intc;chard;};
这个时候的sizeof(node)是多少?20?24?
其实,这个时候你会发现,当你在windows上使用VC编译的时候,你会得到24;当你在linux上使用gcc编译的时候,你会得到20!其实,这恰好说明这种数据的对齐是由编译器决定的!在VC中规定, 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;而在gcc中规定对齐模数最大只能是4,也就是说,即使结构体中有double类型,对齐模数还是4,所以数据是按照1,2,4对齐的。所以,在两个不同编译器上,你得到了不同的答案!
问:sizeof(Node)是多少?答案很简单,在32位机器上,一个int是4个字节,两个int就是8个字节,sizeof(Node)就是8。
好的,上面那个答案确实是8,那么再看下面这个结构体:
structnode{chara;intb;};
问:这个时候sizeof(Node)又是多少呢?int是4个字节,char是1个字节,答案是5?
这回,没有那么幸运,经过在机器上的操作,答案是8! Why?
实际上,这不是语言的问题,你在ANSI C中找不到为什么会这样!甚至你在不同的体系结构、不同的编译器下会得到不同的答案。那么,到底是谁把5改成了8呢?
这就引入了一个概念,叫做“内存对齐”。所谓的内存对齐,是指一种计算机体系结构(如X86)对基本数据类型的存储位置有限制,要求其地址为某个数 的倍数,通常这个数为4或8。这种要求会简化处理器的设计以及提升数据访问的效率。至于为什么会有这样的设计,简单的说访存总线的位数固定,以32位总线 为例,地址总线的地址总是4对齐的,所以数据也四对齐的话,一个周期内就可以把数据读出。这里不理解的话可以跳过去,只要记得对齐这回事儿就行了。如果想 更深入的理解,可以看这里另一篇文章。
知道这个之后,那么我们就可以理解,实际上是编译器为了效率,在相邻的变量之间放置了一些填充字节来保证数据的对齐。X86结构是4对齐的,所以sizeof(Node)是8不是5。
再来看一个例子:
structnode{inta;charb;charc;intd;chard;};
这时的sizeof(Node)是多少呢?没错,是16。
好的,既然我们知道对齐是由编译器来作的,那么我们可不可以更改对齐数呢?答案是可以的,在C语言中,我们可以通过
#pragma pack(n)
来更改对齐模数。
注:以上都是在现x86 linux下使用gcc编译器验证,不乏有其他系统和编译器会得到不同的结果。
再让我们来看个例子:
structnode{doublea;intb;intc;chard;};
这个时候的sizeof(node)是多少?20?24?
其实,这个时候你会发现,当你在windows上使用VC编译的时候,你会得到24;当你在linux上使用gcc编译的时候,你会得到20!其实,这恰好说明这种数据的对齐是由编译器决定的!在VC中规定, 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;而在gcc中规定对齐模数最大只能是4,也就是说,即使结构体中有double类型,对齐模数还是4,所以数据是按照1,2,4对齐的。所以,在两个不同编译器上,你得到了不同的答案!
相关文章推荐
- 关键字的简单总结:static、const、sizeof以及malloc和new、delete和free
- sizeof 关键字
- 对C的某些细节的探讨之sizeof
- sizeof 是一个关键字
- 最冤枉的关键字————sizeof
- 深刻理解void,void*和sizeof关键字
- 探讨C语言中关键字volatile的含义
- 关于ASP.NET访问ACCESS数据的“不能打开注册表关键字”80004005错误的探讨
- sizeof关键字
- 发现C++的sizeof关键字的奇怪问题
- 专题一关键字的剖析----4.goto,void,extern,sizeof的分析
- 关键字sizeof及其十大特性
- sizeof关键字
- sizeof是关键字还是运算符
- void,extern,sizeof 关键字分析
- sizeof 关键字总结
- c++中利用sizeof运算符计算结构体大小问题探讨
- sizeof关键字
- 披着函数外衣的关键字sizeof
- C++中的几个关键字(static、const、#define、inline、sizeof与strlen、指针与引用、new与malloc)