关于struct成员的对齐

jiaoyun007 2013-04-23 09:45:27
各位好,关于struct成员的对齐,有点疑问,请看下面例程:
引用
#include "stdio.h"

#pragma pack(4)

struct s
{
char id;
char number;
int age;
};

int main()
{
printf("sizeof(struct s) = %d\n", sizeof(struct s)) ;
}

结果的输出值是8,如果改变下struct成员顺序,如下:

struct s
{
char id;
int age;
char number;
};
输出结果就是12,我的问题就是,为何当初定义如下时:

struct s
{
char id;
char number;
int age;
};
两个char类型要合用一个对齐单位(4个字节),而不是各自分别按照4字节对齐,谢谢各位!
...全文
280 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiaoyun007 2013-04-25
  • 打赏
  • 举报
回复
引用 9 楼 zhao4zhong1 的回复:
不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 有人说一套做一套,你相信他说的还是相信他做的? 其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗? 不要写连自己也预测……
多谢了,有什么书目推荐的
14号选手 2013-04-25
  • 打赏
  • 举报
回复
引用 13 楼 jiaoyun007 的回复:
引用 11 楼 xuchao1229 的回复:引用 8 楼 jiaoyun007 的回复:引用 7 楼 xuchao1229 的回复:有两个原则 第一个:结构提示按照定义的顺序来存储的,所以每一个元素都是存放在自己长度的整数倍的位置,如果不够则要补齐 第二个:所有元素的长度加起来之后,总长度要是这里面的最大的一个成员的长度的整数倍,如果不是就补齐 就比如你的例子……
呵呵,最好还是自己在DE里面调试一下,看看stack里面的变化就知道了
jiaoyun007 2013-04-25
  • 打赏
  • 举报
回复
引用 16 楼 zhao4zhong1 的回复:
对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是……
真诚的感谢! 不过书还是要沉下心来看的,要领悟其中的思想,上机测试也要做充足的准备才行,您说是吗
赵4老师 2013-04-25
  • 打赏
  • 举报
回复
对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
KevinHo 2013-04-25
  • 打赏
  • 举报
回复
先要看系统位数,32位的就是4字节对齐 另外,参照7楼的两条原则
bsnry 2013-04-25
  • 打赏
  • 举报
回复
csdn就热衷这种题目
jiaoyun007 2013-04-25
  • 打赏
  • 举报
回复
引用 11 楼 xuchao1229 的回复:
引用 8 楼 jiaoyun007 的回复:引用 7 楼 xuchao1229 的回复:有两个原则 第一个:结构提示按照定义的顺序来存储的,所以每一个元素都是存放在自己长度的整数倍的位置,如果不够则要补齐 第二个:所有元素的长度加起来之后,总长度要是这里面的最大的一个成员的长度的整数倍,如果不是就补齐 就比如你的例子 C/C++ code?1234567891……

Yes!
14号选手 2013-04-24
  • 打赏
  • 举报
回复
引用 8 楼 jiaoyun007 的回复:
引用 7 楼 xuchao1229 的回复:有两个原则 第一个:结构提示按照定义的顺序来存储的,所以每一个元素都是存放在自己长度的整数倍的位置,如果不够则要补齐 第二个:所有元素的长度加起来之后,总长度要是这里面的最大的一个成员的长度的整数倍,如果不是就补齐 就比如你的例子 C/C++ code?123456789101112131415#include "s……
旁边有一个添加代码的按钮 记住给分啊,呵呵~~~
彭家老三 2013-04-24
  • 打赏
  • 举报
回复
请楼主参考:
#include <iostream>
using namespace std;

//#pragma pack(1) //使用#pragma pack可以将对齐设置为1
/*
内存对齐的3个准则:
1、结构体变量的首地址能够被其最宽的基本类型成员大小所整除
2、结构体每个成员相对于结构体首地址的偏移量(offset)都是这个成员大小的整数倍,如有不足则补上
3、结构体总大小为结构体最宽的基本类型成员的整数倍
*/
struct widget1
{
	double d;		//sizeof(double)== 8
	int i;			//sizeof(int)	== 4
	short s;		//sizeof(short)	== 2
	char c;			//sizeof(char)	== 1

	static int count;	//count是静态成员,静态成员的空间不在类的实例中,
						//而是像全局变量一样在静态存储区,被类共享。
};
int widget1::count = 0;
/*
对于widget1:
d的偏移量为0;
i的偏移量为8,是sizeof(int)的整数倍,不需补字节
s的偏移量为8+4=12,是sizeof(short)的整数倍,不需补字节
c的偏移量为8+4+2=14,是sizeof(char)的整数倍,不需补字节
目前的结构体的字节数为8+4+2+1=15,不是最大基本变量d大小的整数倍,需要补上1字节,15+1=16
所以sizeof(widget1)==16
*/

struct widget2
{
	
	int i;			//sizeof(int)	== 4
	short s;		//sizeof(short)	== 2
	char c;			//sizeof(char)	== 1
	double d;		//sizeof(double)== 8
};
/*
对于widget2:
i的偏移量为0
s的偏移量为4,是sizeof(short)的整数倍,不需补字节数
c的偏移量为4+2=6,也不需补字节数
d的偏移量为4+2+1=7,但不是sizeof(double)的整数倍,要补字节数1,
所以d的偏移量为4+2+1+1(补齐)=8
目前结构体的字节数为4+2+1+1(补齐)+8=16,是最大基本变量d大小的整数倍,不需补齐
所以sizeof(widget2)==16
*/
struct widget3
{
	char c;			//sizeof(char)	== 1
	int i;			//sizeof(int)	== 4	
	short s;		//sizeof(short)	== 2
	double d;		//sizeof(double)== 8
};
/*
对于widget2:
c的偏移量为0
i的偏移量为1(c的大小)+3(补齐)=4
s的偏移量为1(c的大小)+3(补齐)+4(i的大小)=8
d的偏移量为1(c的大小)+1(补齐)+4(i的大小)+2(s的大小)+6(补齐)=16
目前结构体的大小为1(c的大小)+1(补齐)+4(i的大小)+2(s的大小)+6(补齐)+8(d的大小)=24,不需补齐
所以sizeof(widget3)=24
*/

int main()
{
	cout<<"the size of widget is: "<<sizeof(widget1)<<endl;
	cout<<"the size of widget is: "<<sizeof(widget2)<<endl;
	cout<<"the size of widget is: "<<sizeof(widget3)<<endl;
	system("pause");
	return 0;
}
赵4老师 2013-04-24
  • 打赏
  • 举报
回复
不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 有人说一套做一套,你相信他说的还是相信他做的? 其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗? 不要写连自己也预测不了结果的代码!
jiaoyun007 2013-04-23
  • 打赏
  • 举报
回复
引用 7 楼 xuchao1229 的回复:
有两个原则 第一个:结构提示按照定义的顺序来存储的,所以每一个元素都是存放在自己长度的整数倍的位置,如果不够则要补齐 第二个:所有元素的长度加起来之后,总长度要是这里面的最大的一个成员的长度的整数倍,如果不是就补齐 就比如你的例子 C/C++ code?123456789101112131415#include "stdio.h" #pragma pack(4……
多谢! 再问下,你的代码效果是怎么显示的?
14号选手 2013-04-23
  • 打赏
  • 举报
回复
有两个原则 第一个:结构提示按照定义的顺序来存储的,所以每一个元素都是存放在自己长度的整数倍的位置,如果不够则要补齐 第二个:所有元素的长度加起来之后,总长度要是这里面的最大的一个成员的长度的整数倍,如果不是就补齐 就比如你的例子
#include "stdio.h"

#pragma pack(4)

struct s
{
char id;
char number;
int age;
};

int main()
{
printf("sizeof(struct s) = %d\n", sizeof(struct s)) ;
}
前面是两个char类型,加起来是两个字节(为什么不用补齐,参照第一个原则) 最后一个int类型所占是四个字节,而前面只有两个字节,不是4的整数倍,所以补齐,所以加起来总长度就是2+2+4=8 第二个为什么是12你应该会明白了吧O(∩_∩)O~
Carl_CCC 2013-04-23
  • 打赏
  • 举报
回复
引用 3 楼 jiaoyun007 的回复:
引用 2 楼 Idle_Cloud 的回复:因为32位机器是32位对齐,整数是一个整体,一定要对齐32位,而char,8位就不用一定要放开始,对齐,short就是要16位对齐,方便cpu取数据 你的意思是,对于两个char类型放一起的,CPU每次读4个字节,就可以一次将它们两个都读到?
是的,一次读出来,单不要的会丢掉。
e3internet 2013-04-23
  • 打赏
  • 举报
回复
详细看完你就明白了http://hi.baidu.com/anglecloudy/item/9a844bf88b94c419a62988f0
jiaoyun007 2013-04-23
  • 打赏
  • 举报
回复
引用 2 楼 Idle_Cloud 的回复:
因为32位机器是32位对齐,整数是一个整体,一定要对齐32位,而char,8位就不用一定要放开始,对齐,short就是要16位对齐,方便cpu取数据
你的意思是,对于两个char类型放一起的,CPU每次读4个字节,就可以一次将它们两个都读到?
Carl_CCC 2013-04-23
  • 打赏
  • 举报
回复
因为32位机器是32位对齐,整数是一个整体,一定要对齐32位,而char,8位就不用一定要放开始,对齐,short就是要16位对齐,方便cpu取数据
_树 2013-04-23
  • 打赏
  • 举报
回复
第一个char id占一个字节,第二个char占一个,两个之和小于4个字节就不用各自对齐。如果第二个是int类型,两者之和大于4,char就要按照4字节对齐

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧