大小端模式对union 类型数据的影响



首先重新回忆一下计算机组成原理中的基本概念,数据在内存中的操作是使用补码进行加减操作。int类型占4个字节长度,即32位,char类型占1个字节长度,即8位。

char的范围是  -128~127,unsigned char的取值范围是0~256。原码、反码和补码的转换关系

回忆一下union的特点:所有成员的起始地址一致 union 型数据所占的空间等于其最大的成员所占的空间,对union 型的成员的存取都是相对于该联合体基地址的偏移量为0 处开始,也就是联合体的访问不论对哪个变量的存取都是从union 的首地址位置开始

 80X86一般意味着小端存储和32位操作系统

回忆下大端模式和小端模式

  1. 大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
  2. 小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。

为什么么要有大小端模式?

(自己的理解:因为C语言中有多种数据类型,而同一种处理器位数固定,即处理器中的寄存器每次处理数据位数有限,如果要处理的数据位数大于寄存器的位数,则需要考虑先从低地址位处理还是先从高地址位处理,进而引出了大端小端存储模式)

 在C语言中除了8位的char型之外,还有16的short型,32的long型(要看具体的编译器),对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。

大端模式:

字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。

小端模式

与大端存储模式相反,在小端存储模式中,低地址中存放的是字数据的低字节,高地址存放的是字数据的高字节。

例如,16位宽的数0x1234在 小端模式 CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址

0x4000

0x4001

存放内容

0x34

0x12

而在大端模式CPU内存中的存放方式则为:

内存地址

0x4000

0x4001

存放内容

0x12

0x34

32位宽的数0x12345678在小端模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

内存地址

0x4000

0x4001

0x4002

0x4003

存放内容

0x78

0x56

0x34

0x12

而在端模式CPU内存中的存放方式则为:

内存地址

0x4000

0x4001

0x4002

0x4003

存放内容

0x12

0x34

0x56

0x78


        我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。

例题:

1
2
3
4
5
6
7
8
9
10
11
union Test
  {
     char  a[ 4 ];
     short  b;
  };
  Test test;
  test.a[ 0 ]= 256 ;
  test.a[ 1 ]= 255 ;
  test.a[ 2 ]= 254 ;
  test.a[ 3 ]= 253 ;
  printf( "%d\n" ,test.b);
问题:在80X86架构下,输出什么值?


char类型的取值范围是-128~127,unsigned char的取值范围是0~256
这里a[0]=256,出现了正溢出,将其转换到取值范围内就是0,即a[0]=0;
同理,a[1]=-1, a[2]=-2, a[3]=-3,在C语言标准里面,用补码表示有符号数,故其在计算机中的表示形式如下:
a[0]=0,     0000 0000
a[1]=-1,    1111 1111
a[2]=-2,    1111 1110
a[3]=-3,    1111 1101
short是2字节(a[0]和a[1]),由于80X86是小端模式,即数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中,在本例中,a[0]中存放的是b的低位,a[1]中存放的是b的高位,即b的二进制表示是:1111 1111 0000 0000,表示-256
计算过程如下:

char a[0]=256;
val=-128+(256-128)%256=0            ====>a[0]:00000000
char a[1]=255;
val=-128+(255-128)%256=-1            ====>a[1]:11111111
10000001(-1源码)
11111110(-1反码)
11111111(-1补码)

80X86-->小端模式 数据低位--->内存低地址
test共4字节
            test     XXXXXXXX   XXXXXXXX   XXXXXXXX   XXXXXXXX
低地址 a[0]                                                              00000000
            a[1]                                           11111111
            a[2]                        ........
            a[3]    ........

====>short 11111111 00000000(补码)
                   10000000 11111111( 反码)
                   10000001 00000000(源码-256) 




个人愚见 ,仅供参考,欢迎拍砖,共同学习。

部分内容引用自一下网页,如果侵权,联系删除。

http://blog.csdn.net/vevenlcf/article/details/46924267

http://c.biancheng.net/cpp/html/450.html

https://www.nowcoder.com/questionTerminal/c7298be0b2ce42698b80987631cf8fca


你可能感兴趣的:(渣渣入门记)