永发信息网

C++中结构体的大小

答案:6  悬赏:50  手机版
解决时间 2021-03-26 01:57
C++中结构体的大小
最佳答案
结构体(struct)的sizeof值,并不是简单的将其中各元素所占字节相加,而是要考虑到存储空间的字节对齐问题。先看下面定义的两个结构体.
struct
{
char a;
short b;
char c;
}S1;
struct
{
char a;
char b;
short c;
}S2;
分别用程序测试得出sizeof(S1)=6 , sizeof(S2)=4
可见,虽然两个结构体所含的元素相同,但因为其中存放的元素类型顺序不一样,所占字节也出现差异。这就是字节对齐原因。通过字节对齐,有助于加快计算机的取数速度,否则就得多花指令周期。
字节对齐原则
结构体默认的字节对齐一般满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset,即每个成员的起始地址)都是成员自身大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
注意:当结构体成员里面有数组成员时,如int a[10],要看成10个整形变量才参与计算。

通过这三个原则,就不难理解上面两个struct的差异了.
对于struct S1, 为了使short变量满足字节对其准则(2), 即其存储位置相对于结构体首地址的offset是自身大小(short占2个字节)的整数倍,必须在字节a后面填充一个字节以对齐;再由准则(3),为了 满足结构体总大小为short大小的整数倍,必须再在c后面填充一个字节。

对于struct S2, 却不必如上所述的填充字节,因为其直接顺序存储已经满足了对齐准则。
如果将上面两个结构体中的short都改为int(占4个字节), 那么会怎么样呢? 程序得出sizeof(S1)=12, sizeof(S2)=8
利用上面的准则,也不难计算得出这样的结果。S1中在a后面填充3个字节、在c后面填充3个字节,这样一共12个字节;S2中在a、b顺序存储之后填充两个字节用以对其,这样一共就8个字节。
当然,在某些时候也可以设置字节对齐方式。这就需要使用 #pragma pack 。
#pragma pack(push) //压栈保存
#pragma pack(1)// 设置1字节对齐
struct
{
char a;
short b;
char c;
}S1;
#pragma pack(pop) // 恢复先前设置
如上所示,将对其方式设为1字节对齐,那么S1就不填充字节,sizeof为各元素所占字节之和即4。这一点在从外部2进制文件中读入struct大小的数据到struct中,是很有用的.
另外,还有如下的一种方式:
· __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
· __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。
全部回答
首先说明一下,编译器不一样,结果也不一样,造成不同的原因归结于默认类型不同,内存补齐的大小不同,如果在vc下,int默认为long int ,即大小为4字节,vc内存补齐的大小也为4字节,(编译器分配的内存不是按变量大小分配的,一个char虽然是1字节,但编译器会分配4字节,如果再配一个char,那么就存储在当前的这个剩下3字节的内存中,但要是再分配各int,剩下的2字节就不够用了,所以再分配4字节,至于那2字节,就浪费掉了^_^)。按着这种规则,sizeof(s)== 20;
在32位的操作系统中是: 24个
编译器为了提高cpu的处理速度,会对内存进行对齐
重载运算符啊~~
PS:结构体=类,只是默认数据保密类型和继承类型不一样而已...
给个例子:
#define size_max UINT_MAX//字符串长度的最大值
typedef unsigned STR_SIZE_TYPE;//字符串长度变量声明
typedef char STR_CHAR;//字符串字符类型
const unsigned NAGASA=16;//重载>>中内存开辟递增数量级
struct string
{
private:
STR_CHAR *str;
STR_SIZE_TYPE len;
protected:
public:
string();
string(const STR_CHAR &);
string(const STR_CHAR *);
string(const string &,STR_SIZE_TYPE n=0,STR_SIZE_TYPE m=size_max);
string(const STR_SIZE_TYPE &,const STR_CHAR &);
string(const STR_CHAR *,const STR_SIZE_TYPE &);
virtual ~string();
string & operator =(const string &);
string & operator =(const STR_CHAR *);
string & operator =(const STR_CHAR &);
string & operator +=(const string &);
string & operator +=(const STR_CHAR *);
string & operator +=(const STR_CHAR &);
STR_CHAR & operator [](const STR_SIZE_TYPE & i);
const STR_CHAR & operator [](const STR_SIZE_TYPE & i)const;
STR_SIZE_TYPE size()const
;
STR_SIZE_TYPE has(const STR_CHAR &)const;//返回string对象中指定参数字符的数量
void up();//将string对象中的小写字母转换为大写字母
void low();//将string对象中的大写字母转换为小写字母
void swap(string &);
bool empty()const;
void resize(const STR_SIZE_TYPE,const STR_CHAR ch=' ');
void clear();
friend std::ostream & operator <<(std::ostream &,const string &);
friend std::istream & operator >>(std::istream &,string &);
friend bool operator <(const string &,const string &);
friend bool operator >(const string &,const string &);
friend bool operator ==(const string &,const string &);
friend bool operator !=(const string &,const string &);
friend bool operator <=(const string &,const string &);
friend bool operator >=(const string &,const string &);
friend string operator +(const string &,const string &);
friend void swap(string &,string &);
typedef STR_SIZE_TYPE size_type;
};
bool operator <(const string & st1,const string & st2)
{
if(strcmp(st1.str,st2.str)<0)
{
return true;
}
else
{
return false;
}
}
bool operator >(const string & st1,const string & st2)
{
if(strcmp(st1.str,st2.str)>0)
{
return true;
}
else
{
return false;
}
}
bool operator ==(const string & st1,const string & st2)
{
if(0==strcmp(st1.str,st2.str))
{
return true;
}
else
{
return false;
}
}
bool operator !=(const string & st1,const string & st2)
{
if(0==strcmp(st1.str,st2.str))
{
return false;
}
else
{
return true;
}
}
bool operator <=(const string & st1,const string & st2)
{
if(strcmp(st1.str,st2.str)>0)
{
return false;
}
else
{
return true;
}
}
bool operator >=(const string & st1,const string & st2)
{
if(strcmp(st1.str,st2.str)<0)
{
return false;
}
else
{
return true;
}
}
4+1+4+8=17
如果相邻的位域字段的类型不同
根据各自编译器去处理。
不压缩则
int 4 字节
char 1字节
int 4字节
double 8字节
由于要字节对齐,则取最大的8位对齐
前两个 int char 之和 是 5字节,如果再加4字节就超过8自己饿了。
所以他们空出最后3字节
第三个int 占8字节,空出后面4个字节。
double占8个字节
所以一共事 3 * 8 = 24
=====================
考虑压缩情况:
还是按8位对齐。
前3个经过压缩,实际占1自己多,但考虑对齐,所以后面空出6字节多
double自己占8个字节。
所以总和是:2 * 8 = 16字节。
具体是多少,看编译器处理了。
估计VC和GCC应该俩结果
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
触摸精灵怎么用?录制失败001
我已经相信有些人我永远不必等 所以我明白在
刘邦和项羽谁是好人
结构建筑按结构形式分为上部结构和下部结构。
5,7,8,10如何运算等于24?
收入12000缴纳多少个人所得税
k596次列车经过昆山吗?
九阳豆浆机原价899无渣的打完还有不少渣怎么
18考研知道这几条,成功几率提高5成
联想笔记本s510p最新价格是多少
钢正火后的组织是什么
网红Mc茉莉最喜欢的女明星是谁阿?
Use by JUN 2019是什么意思
by jeep, we visited a number of cities in
企业未年报公示有什么后果
推荐资讯
李亮的弃高薪毅然回国
科班出身是什么意思?
魔兽世界7.0 魔兽鲁克玛刷新时间多久刷新
CSOL目前最新的加速基址是多少?
木栾大道都有那些物流公司
写广元女儿节的作文很有趣的,必须是有趣的哟!
为什么车可以当船开?
什么植物适宜摆放在家中
东北亚北方交易所武汉千珏会员单位
怎样能使卷边发硬的全羊毛围巾能变软呢!
素馅荠菜包子的做法大全集
我在桂林了要怎么去临贵榕山路?
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?