内存大小端

目录

一,大端Big_endian、小端Little_endian

二,字节大小端

1,int

2,结构体

三,比特大小端

四,总结


一,大端Big_endian、小端Little_endian

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这和我们的阅读习惯一致。

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。

大小端的问题,主要有2个颗粒度,一个是字节,一个是比特。

二,字节大小端

当一个数据有n(n>1)个字节组成时,我们才需要考虑大小端,如果所有数据都是一个字节的大小,就没有大小端了。

一个字节的数据以char为代表,而n(n>1)个字节的数据以int这种原子数据为代表,结构体这种复合数据不涉及字节大小端。

在用指针转换来完成大小端实测之前,首先我们要知道:

无论大小端,也无论是int还是结构体类型的指针,指针指向的那个字节都是所有字节中最低的那个

1,int

代码:

#include <stdio.h>

int main()
{
    int a=257;
    char *p=(char *)&a;
    printf("%d %d %d %d",*p, *(p+1),*(p+2),*(p+3));
    return 0;
}

输出:1 1 0 0

很明显,这是小端,个人PC默认是小端。

如果是大端环境,输出的就是0 0 1 1了

2,结构体

代码:

#include <stdio.h>

typedef struct Node
{
    int a;
    int b;
}Node;

int main()
{
    Node s;
    s.a=1,s.b=257;
    char *p=(char *)&s;
    for(int i=0;i<8;i++)printf("%d ",*(p+i));
    return 0;
}

输出:1 0 0 0 1 1 0 0

如果是大端环境,输出的就是1 1 0 0 1 0 0 0

也就是说,结构体内各成员的顺序就是自然顺序,没有大小端之分,但是成员内部还是按照成员本身的规则安排。

因为结构体可以嵌套结构体,所以我上面这句话其实也是个递归式的论述。

三,比特大小端

当使用位域时,我们需要考虑字节内各比特位的排列顺序,即比特大小端。

在网上找到一个示例:

struct Node{
    int a:1;
    int b:2;
    int c:3;
    int d:4;
    int e:5;
    int f:6;
    int g:11;
};

大端:
数据:abbcccdd ddeeeeef fffffggg gggggggg
小端:
数据:ddcccbba feeeeedd gggfffff gggggggg

同样的,我用小端机器输出试了下:

#include <stdio.h>

typedef struct Node
{
    int a:1;
    int b:2;
    int c:29;
}Node;

int main()
{
    Node s;
    s.a=1,s.b=2,s.c=3;
    printf("%d",s);
    return 0;
}

输出:29 即(11101)

四,总结

如果抛弃字节的概念,把所有内存都看成按低比特到高比特的排列,那么规律就比较简洁统一:

(1)大端就是高位在低比特,小端就是高位在高比特,所有原子类型都符合这个排列规则

(2)结构体成员按照成员顺序从低比特到高比特排列,无论是大端还是小端,无论是普通原子类型还是结构体还是位域。而结构体成员内部的比特排列,按照规则递归定义。

猜你喜欢

转载自blog.csdn.net/nameofcsdn/article/details/114134721