大端小端及其union的练习题

看了这个例子,一定会有这样的疑问:应该是00 00 00 01,为什么会是这样的

    vs2013是小端存储,下面的这个图从左到右地址是由低到高。

比如0x11223344在大端机上是11223344,在小端机上是44332211。

大端:低地址存高位

小端:低地址存低位 (小弟弟)

先来说清楚,32位内存地址的,虽然我们在看一个二进制数的时候比如01111011,是从后往前看的,这样看来从左到右是高地址到低地址,而在内存中,一般是由低地址到高地址的,可以看下面的这个图:

左边的0x0000000E从上到下是从小到大的,所以看存储的一个数在大端机上的是怎么样的,在小端机上是怎么样的。反正从左到右是低地址到高地址。

上面说的高位低位指的是权重,比如说1234这个数字,1的权重是千,1就是高位,高低位是相对的。

位指的是权重

如何判断数据的高位与低位因为位指的是权重,那么比如说1234这个数字,1的权重是千,1就是高位,高低位是相对的。

比如对于11223344来说,他的最低位就是4,最高位就是1,则在大端机器上是11223344,在小端机器上是44332211

为什么有大端小端之分,因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。
但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器。例如16位或者32位的处理器,
由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题(也就是将数据的字节如何与内存中的地址对应的问题)。因此就导致了大端存储模式和小端存储模式。
看一个例题:在小端模式下,下面的代码输出是

#include<iostream>
using namespace std;

union Un
{
    short a;//2
    char b;//实际对齐数是1
}un;//总体对齐数是2

int main()
{
    char p[] = {2,1};
    Un*n = (Un*)p;//这个是将p指针扩充为Un大小的(为两个子节),所以是
    printf("%d,%d\n",n->a,n->b);

    return 0;

}

 

#include<iostream>
using namespace std;

union Un
{
    short a;//对齐数是2
    char b;// 对齐数是1
}un;//总体对齐数是2

int main()
{

    char p[] = {2,1};//00000010,0000 0001
    Un*n = (Un*)p;//扩充为两个字节的,,这样识别的16位就是一个数,这个其实是将char 数组里的赋值给联合体里的变量。
    //00000010 00000001
    //如果是小端机器,说明将
    printf("%d,%d\n",n->a,n->b);//联合体,所以a和b共用一块内存,所以是,所以用n指针去访问肯定是0000 0001 0000 0010。因为输出是%d,也就是4个子节,所以不用截断,
    //也就是258 而后面的b是一个字节,所以是需要截断的,所以是0000 0001 0000 0010的后八位,所以是2
//这个的之所以没有覆盖是因为,他实际访问的是p指向的那块内存,而不是通过赋值,所以是不会覆盖的

    // 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010  


    /*
    un.a = 1, un.b = 2; //0000 0001 0000 0010。
    printf("%d,%d\n", un.a, un.b);//输出为%d,是int类型的。所以肯定是2,然后将其扩充为4个子节
    */
    return 0;

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章