按位分配数据空间、结构体按位分配空间的细节与内存对齐

/*

**test23.cpp : Defines the entry point for the console application.

**系统winXP SP3 32位.

**按位分配数据空间、结构体按位分配空间的细节与内存对齐

*/


#include "stdafx.h"

#include "iostream.h"


enum Color{RED = 0x01, GREEN, WHITE, BLACK};


struct SS{

bool ss_bNum1;   //1个字节

Color ss_color;   //4个字节

bool ss_bNum2;   //1个字节

double ss_dNum;   //8个字节

unsigned char ss_ucNum;   //1个字节

};


struct SC{

unsigned int iNum1;

unsigned int iNum2 : 4;

unsigned int iNum3 : 5;

unsigned int iNum4 : 5;

unsigned int iNum5 : 6;

unsigned int iNum6 : 6;

//unsigned int iNum7 : 0;   //注意这里定义为0的位数会迫使在其后面分配bit的变量从新得完整的一个机器字(4个字节)开始

//unsigned int iNum8 : 33;   //不允许超过最大位数

//unsigned int iNum9 : 7;   //这里总计超过了32bit,所以要在分配一个最小内存空间,注意多出来的部分不会按位、或字节分配,而是直接分配了4个字节,所以下面的输出结果为12

};


int main(int argc, char* argv[])

{

char c;

SC sc;

cout<


cout<<sizeof(bool)<<endl; //1

cout<<sizeof(Color)<<endl; //4

cout<<sizeof(unsigned char)<<endl; //1

cout<<sizeof(double)<<endl; //8


SS ss;

cout<<sizeof(ss)<<endl; //32,,,为什么不是15呢


cout<<&ss.ss_bNum1<<endl; //首地址0x0012FF58,占据了4个字节,浪费

cout<<&ss.ss_color<<endl; //首地址0x0012FF5C,占据了4个字节,正好

cout<<&ss.ss_bNum2<<endl; //首地址0x0012FF60,由于要内存对齐,故占据了8个字节,浪费

cout<<&ss.ss_dNum<<endl; //首地址0x0012FF68,占据了8个字节,正好

printf("0x%p\n",&ss.ss_ucNum); //首地址0x0012FF70,满足对象数数据类型边界对齐,故占据了8个字节,浪费,

//从上面的地址输出我们可以看出Tips4内存对齐的作用,虽然将访问效率大大提升,但浪费了很多的内存空间

//注意这里cout对于输出char*与char类型地址需要使用printf格式化%p输出,否则乱码


return 0;

}



Tips1:我们知道一个字节8bit,而在32位系统中会存在内存浪费的现象,如bool类型应该占1个字节,8bit,但32位系统CPU最小处理32bit的数据,所以多出来的内存空间都会被浪费掉。

Tips2:关于寻址:如果要是有只占用一个 bit 的变量,那么它保存的时候也应该是只占用一个 bit,假设这一个 bit 放在一个空的byte 的首位,那么剩下的七个 bit要怎么处理呢?存东西还是不存东西?如果要存,那么之后的顺序就都乱了——所以地址值要具体到每一个 byte 了,8 =2^3,所以地址值直接增加三位,这样整个系统的代价太大了。故直接用 byte来保存,浪费一点是难免的。(类似于结构体的字节对齐现象)。

Tips3:如果想尽量减少浪费的内存应该怎么做呢?适用于位域的数字类型要求是int、unsigned int、signed int、char、long等,不可以是指针类型或浮点类型。

Tips4:内存对齐:为是访问效率更高,double变量的地址要可以被8整除,char、bool可以被1整除

推荐阅读更多精彩内容