/*
**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整除