【无标题】

2024-01-09 21:39:54

1. 关于大小端存储的概念

首先需要一些概念:

对于一个 ω \omega ω位的整数,其位表示为[x ω \omega ω-1, x ω \omega ω-2, …, x2, x1]。其中:

  • 最高有效字节: [x ω \omega ω-1, x ω \omega ω-2, …, x ω \omega ω-7, x ω \omega ω-8];
  • 最低有效字节: [x7, x6, …, x1, x0];
  • 大端法(big endian):最高有效字节位于内存的低地址;最低有效字节位于内存的高地址;

为方便记忆,可以将大端法类比为日常手写数字的顺序,左侧(内存中的低地址)是数字高位有效数字,右侧是低位数字。

  • 小端法(little endian):与大端法相反

以32位int整数0x12345678为例,该int位于内存的地址位0x100,则两种情况的内存分布为:

2. 关于大小端存储的应用

  1. 不同存储的设备通过网络收发二进制数据,如果收发的设备不同,发送的顺序会与接受顺序相反。具体看CSAPP第12章(暂未看到)
  2. 关于小端存储机器级指令的阅读:
    4004d3: 01  05  43  0b  20  00      add     %eax,0x200b43(%rip)
    
    已知上述代码设计两个数相加:PC寄存器中的值和0x200b43。0x200b43这个值位于指令的最后四个字节:43 0b 20 00, 根据小端存储的定义并去掉第一个符号位字节,该数值即为20 0b 43

3.通过C代码测试本机器是小端存储还是大端存储

#include <stdio.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, size_t len) {
        size_t i;
        for (i = 0; i < len; ++i) {
                printf(" %.2x", start[i]);
        }
        printf("\n");
}

// 使用sizeof并用size_t类型接受,从而不受编译环境的影响·
void show_int(int x) {
        show_bytes((byte_pointer)&x, sizeof(int));
}
void show_float(float x) {
        show_bytes((byte_pointer)&x, sizeof(float));
}

void show_void(void *x) {
        show_bytes((byte_pointer)&x, sizeof(void *));
}

void test_show_bytes(int val) {
        int ival = val;
        float fval = (float) ival;
        int *pval = &ival;
        show_int(ival);
        show_float(fval);
        show_void(pval);
}
int main()
{
        test_show_bytes(12345);
        return 0;
}

以下是在Linux 32bit和Linux 64bit测试结果:

## linux 32
 39 30 00 00
 00 e4 40 46
 04 79 84 bf
## linux 64
 39 30 00 00
 00 e4 40 46
 a8 72 70 39 fd 7f 00 00

十进制12345的十六进制表示位0x00003039, 上述机器均为小端存储。

还有其他的巧妙测试方法:

  1. 强制转换:
    #include <iostream>
    using namespace std;
    int main()
    {
        int a = 0x1234;
        //由于int和char的长度不同,借助int型转换成char型,只会留下低地址的部分
        char c = (char)(a);
        if (c == 0x12)
            cout << "big endian" << endl;
        else if(c == 0x34)
            cout << "little endian" << endl;
    }
    
  2. 使用联合体
    #include <iostream>
     using namespace std;
     //union联合体的重叠式存储,endian联合体占用内存的空间为每个成员字节长度的最大值
     union endian
     {
         int a;
         char ch;
     };
     int main()
     {
         endian value;
         value.a = 0x1234;
         //a和ch共用4字节的内存空间
         if (value.ch == 0x12)
             cout << "big endian"<<endl;
         else if (value.ch == 0x34)
             cout << "little endian"<<endl;
     }
    

上述两种方法参考来源:阿秀的校招笔记

文章来源:https://blog.csdn.net/weixin_43869409/article/details/135488494
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。