在程序中,数据结构还有变量等等都需要占有内存,在很多系统中,它都要求内存分配的时候要对齐,这样做的好处就是可以提高访问内存的速度.
如果我们的内存分配的都很零碎,那么当系统长时间运行时会出现系统的内存碎片.内存并没有用完全被用完,而是留下一些零星的小的内存空间.
这样的话对于我们的程序是很不好的,今天就来谈谈C++的结构体的设计.
我们先定义一个结构体:
结构体1:
//32位系统下
typedef struct tagDevInfo
{
short iRegType;// 2
int iDevType;// 4
char chDevName[16]; //16
const tagDevInfo& operator=(const tagDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}DEV_INFO;
上面的结构体大小Win32编译器下是:24
正常情况下我们计算得到大小是22,编译器帮我门优化加了两个字节,那么那两个字节在哪里呢?
//32
typedef struct remDevInfo
{
double iDevType; // 8
short iRegType;// 2
char chDevName[16]; //16
const remDevInfo& operator=(const remDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}RDEV_INFO;
上面的结构体大小Win32编译器下是:32,系统补了6个字节,这6个字节从上面的例子可以看到,初始化内存块大小为8,iRegType字节不够需要补齐6个字节凑成8个字节.
一般来说我们结构体对齐的原则如下:、
1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该
成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。
3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
对于上述结构体如何优化呢?
//结构体1,32位系统
typedef struct tagDevInfo
{
short iRegType;// 2
short reserved;// 2 保留位
int iDevType;// 4
char chDevName[16]; //16
const tagDevInfo& operator=(const tagDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}DEV_INFO;
结构体2:
//32位系统
typedef struct remDevInfo
{
double iDevType; // 8
short iRegType;// 2
short reserved[3];// 6 保留位
char chDevName[16]; //16
const remDevInfo& operator=(const remDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}RDEV_INFO;
小练习:
typedef struct tagDevInfo
{
short iRegType;// 2
int iDevType;// 4
char chDevName[16]; //16
const tagDevInfo& operator=(const tagDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}DEV_INFO;
typedef struct remDevInfo
{
double iDevType;
int iRegType[3];
char chDevName[16];
DEV_INFO* pdevInfo;
int channel;
const remDevInfo& operator=(const remDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}RDEV_INFO;
这里RDEV_INFO如何优化呢?
答案:
typedef struct remDevInfo
{
double iDevType;
int iRegType[3];
int reserved;
char chDevName[16];
DEV_INFO* pdevInfo;
int channel;
const remDevInfo& operator=(const remDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}RDEV_INFO;
win32编译器下大小为:48
如果我们的内存分配的都很零碎,那么当系统长时间运行时会出现系统的内存碎片.内存并没有用完全被用完,而是留下一些零星的小的内存空间.
这样的话对于我们的程序是很不好的,今天就来谈谈C++的结构体的设计.
我们先定义一个结构体:
结构体1:
//32位系统下
typedef struct tagDevInfo
{
short iRegType;// 2
int iDevType;// 4
char chDevName[16]; //16
const tagDevInfo& operator=(const tagDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}DEV_INFO;
上面的结构体大小Win32编译器下是:24
正常情况下我们计算得到大小是22,编译器帮我门优化加了两个字节,那么那两个字节在哪里呢?
从下面的图可以看出来,编译器优化的两个字节实在iRegType后面,为什么补了两个字节呢?
//32
typedef struct remDevInfo
{
double iDevType; // 8
short iRegType;// 2
char chDevName[16]; //16
const remDevInfo& operator=(const remDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}RDEV_INFO;
上面的结构体大小Win32编译器下是:32,系统补了6个字节,这6个字节从上面的例子可以看到,初始化内存块大小为8,iRegType字节不够需要补齐6个字节凑成8个字节.
一般来说我们结构体对齐的原则如下:、
1、数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该
成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。
2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。
3、收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
对于上述结构体如何优化呢?
//结构体1,32位系统
typedef struct tagDevInfo
{
short iRegType;// 2
short reserved;// 2 保留位
int iDevType;// 4
char chDevName[16]; //16
const tagDevInfo& operator=(const tagDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}DEV_INFO;
结构体2:
//32位系统
typedef struct remDevInfo
{
double iDevType; // 8
short iRegType;// 2
short reserved[3];// 6 保留位
char chDevName[16]; //16
const remDevInfo& operator=(const remDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}RDEV_INFO;
小练习:
typedef struct tagDevInfo
{
short iRegType;// 2
int iDevType;// 4
char chDevName[16]; //16
const tagDevInfo& operator=(const tagDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}DEV_INFO;
typedef struct remDevInfo
{
double iDevType;
int iRegType[3];
char chDevName[16];
DEV_INFO* pdevInfo;
int channel;
const remDevInfo& operator=(const remDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}RDEV_INFO;
这里RDEV_INFO如何优化呢?
答案:
typedef struct remDevInfo
{
double iDevType;
int iRegType[3];
int reserved;
char chDevName[16];
DEV_INFO* pdevInfo;
int channel;
const remDevInfo& operator=(const remDevInfo& rhs)
{
if (&rhs != this)
{
memcpy(this, &rhs, sizeof(rhs));
}
return *this;
}
}RDEV_INFO;
win32编译器下大小为:48