C++中结构体的大小
答案:6 悬赏:50 手机版
解决时间 2021-03-26 01:57
- 提问者网友:浩歌待明月
- 2021-03-25 09:51
C++中结构体的大小
最佳答案
- 五星知识达人网友:天凉才是好个秋
- 2021-03-25 11:07
结构体(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)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。
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)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。
全部回答
- 1楼网友:蓝房子
- 2021-03-25 15:50
首先说明一下,编译器不一样,结果也不一样,造成不同的原因归结于默认类型不同,内存补齐的大小不同,如果在vc下,int默认为long int ,即大小为4字节,vc内存补齐的大小也为4字节,(编译器分配的内存不是按变量大小分配的,一个char虽然是1字节,但编译器会分配4字节,如果再配一个char,那么就存储在当前的这个剩下3字节的内存中,但要是再分配各int,剩下的2字节就不够用了,所以再分配4字节,至于那2字节,就浪费掉了^_^)。按着这种规则,sizeof(s)== 20;
- 2楼网友:枭雄戏美人
- 2021-03-25 14:23
在32位的操作系统中是: 24个
编译器为了提高cpu的处理速度,会对内存进行对齐
编译器为了提高cpu的处理速度,会对内存进行对齐
- 3楼网友:你哪知我潦倒为你
- 2021-03-25 14:11
重载运算符啊~~
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;
}
}
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楼网友:西风乍起
- 2021-03-25 13:13
4+1+4+8=17
- 5楼网友:英雄的欲望
- 2021-03-25 11:43
如果相邻的位域字段的类型不同
根据各自编译器去处理。
不压缩则
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应该俩结果
根据各自编译器去处理。
不压缩则
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应该俩结果
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
推荐资讯