联合体、结构体的一些整理

联合体:
采用 Little-endian 模式的 CPU 对操作数的存放方   式是从低字节到高字节,而 Big-endian 模式对操作数的存放方式是从高字节到低字节。例如, 16bit 宽的数 0x1234 Little- endian 模式 CPU 内存中的存放方式(假设从地址 0x4000 开始存放)为:
内存地址   存放内容  
0x4000 0x34 
0x4001 0x12 
而在 Big-endian 模式 CPU 内存中的存放方式则为:
内存地址   存放内容  
0x4000 0x12 
0x4001 0x34 
  1. main()
  2. {
  3.     union{             
  4.          inti;
  5.         struct{          
  6.             charfirst;
  7.             charsecond;
  8.         }half;
  9.     }number;
  10.     number.i=0x4241;       
  11.                                     number.half.first = 0x41, number.half.second = 0x42
  12.     number.half.first='a';  
  13.     number.half.second='b';
  14.                                      number.i = 0x6261
  15. }
  16. number.i 和 number.half 共用一块内存空间, 内存大小为两者中较大的内存大小。          
结构体:
结构中的变量按照类型大小从大到小或者从小到大顺序声明 , 尽量减少中间的填补空间
1为什么要进行字节对齐

看下面的数据结构声明:

 
struct A
{ 
char c; 
int i; 
};
struct A a;

   假设变量a存放在内存中的起始地址为0x00,那么其成员变量c的起始地址为0x00,如果不考虑字节对齐成员变量i的起始地址为0x01,变量a一共占用了5个字节。如若CPU要对成员变量i进行访问,那么情况就变得有点复杂了,首先CPU用了一个读周期,从0x00处读取了4个字节(注意由于是32位架构),然后将0x01-0x03的3个字节暂存,接着又花费了一个读周期读取了从0x04-0x07的4字节数据,将0x04这个字节与刚刚暂存的3个字节进行拼接从而读取到成员变量i的值。为了读取这个成员变量i,CPU花费了整整2个读周期。试想一下,如果数据成员i的起始地址被放在了0x04处,那么读取其所花费的周期就变成了1,显然引入字节对齐可以避免读取效率的下降,但这同时也浪费了3个字节的空间(0x01-0x03)。这也是空间和时间的博弈。

 

2 先让我们看四个重要的基本概念:
1.数据类型自身的对齐值:
    : 对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,系统会给数组一个元素一个元素的分配内存空间,单位字节。
2.结构体或者类的自身对齐值:

   :其成员中自身对齐值最大的那个值。
3.指定对齐值:

   :#pragma pack(value)时的指定对齐值value。
4.数据成员、结构体和类的有效对齐值:

   :自身对齐值和指定对齐值中小的那个值。

有效对齐N,就是表示“对齐在N上”,也就是说该数据的"存放起始地址%N=0"。.而数据结构中的数据变量都是按定义的先后顺序来排放的。

 例:假设在x86机器上,假设编译器按默认4字节进行对齐。


struct
{ 
char c; 
   int i;
   short s; 
};  

首先来看sizeof(struct A),假设A的起始地址为0x00,做这样的假设只是为了更方便理解,其实A始终被放在对齐边界上。
    数据成员c的自身对齐值=1,指定对齐值=4,所以其有效对齐值为1,因0x00%1==0,所以它被存放在0x00处;数据成员i的自身对齐值=4,指定对齐值=4,可得出其有效对齐值为4,因0x01%4 != 0,因此它应该被存放在0x04地址处,并占用0x05,0x06,0x07共4个字节;接下来看数据成员s的自身对齐值=2,指定对齐值=4,得出有效对齐值为2,因0x08%2 == 0,因此它被存放在起始地址为0x08处,并占用2字节;最后再看数据结构A自身的对齐值=4(最大数据成员自身对齐值),指定对齐值=4,得有效对齐值为4,对于结构体或者类,要将它们补充成其有效对齐值的整数倍,这点请千万注意)。由此可见sizeof(struct A)的结果应该是=1+3(空闲空间)+4+2+2(结构体补充)=12字节

你可能感兴趣的:(数据结构,c,struct,float,编译器,X86)