【基础知识系列】用示例一窥字节序-大小端

代码示例

示例代码分别在mac与android的开发环境下测试主机的字节序,还有通过IDE分析一个Int整型在内存的实际存储,于"肉眼可视"的方式去观察数据在内存的存储情况,加深与理解字节大小端。代码示例了两种方式判断主机字节序是否为小端字节序

mac 环境示例

代码

#include 

using namespace std;

bool isLittleEndian() {
    int i = 1;
    //强转char指针,即指向int的首字节,可访问int的首字节的内容/值
    char *a = (char *) &i;
    return *a == 1;
}

bool isLittleEndian2() {
    union {
        int i;
        char c;
    } un;
    //char跟int是共用内存块,然后内存对的,即char跟int的首字节是同一块内存空间
    un.i = 1;
    return un.c == 1;
}

int main() {

    int x = 0x12345678;
    char *p = (char *) &x;

    cout << "逻辑上的顺序: 0x 12 34 56 78" << endl;
    printf("内存中的顺序: 0X %0x % 0x %0x %0x \n", p[0], p[1], p[2], p[3]);

    cout << "当前主机序字节序是: ";
    if (isLittleEndian()) {
        cout << "小端"<< endl;
    } else {
        cout << "大端" << endl;
    }

    cout << "当前主机序字节序是: ";
    if (isLittleEndian2()) {
        cout << "小端"<< endl;
    } else {
        cout << "大端" << endl;
    }

    return 0;
}

运行结果

【基础知识系列】用示例一窥字节序-大小端_第1张图片

结论:OSX 系统的主机字节序是小端/ little-endian

PS: 苹果官网文档也有说明的,MAC电脑,包括最新出M1、M2 都是小端序
【基础知识系列】用示例一窥字节序-大小端_第2张图片

运行时内存

使用Clion IDE的Memory View功能!
【基础知识系列】用示例一窥字节序-大小端_第3张图片
如下是上述代码示例中x变量在内存中的存储情况
【基础知识系列】用示例一窥字节序-大小端_第4张图片

Android环境示例

代码

native-lib.cpp文件的内容

#include 
#include 
#include 

using namespace std;

static char* TAG = "Demo";

bool isLittleEndian() {
    int i = 1;
    char *a = (char *) &i;
    return *a == 1;
}

bool isLittleEndian2() {
    union {
        int i;
        char c;
    } un;
    un.i = 1;
    return un.c == 1;
}

void testEndian() {

    int x = 0x12345678;
    char *p = (char *) &x;

    __android_log_print(ANDROID_LOG_INFO, TAG, "0x %x %x %x %x", p[0], p[1], p[2], p[3]);

    if (isLittleEndian()) {
        __android_log_print(ANDROID_LOG_INFO, TAG, "小端");
    } else {
        __android_log_print(ANDROID_LOG_INFO, TAG, "大端");
    }

    if (isLittleEndian2()) {
        __android_log_print(ANDROID_LOG_INFO, TAG, "小端");
    } else {
        __android_log_print(ANDROID_LOG_INFO, TAG, "大端");
    }
}


extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    testEndian();
    return env->NewStringUTF(hello.c_str());
}

运行结果

【基础知识系列】用示例一窥字节序-大小端_第5张图片
结论:Linux/Android 系统 的主机字节序是小端/little-endian

运行时内存

PS: 使用AS的Memory View功能!
【基础知识系列】用示例一窥字节序-大小端_第6张图片

大小端 big/little enidan

为什么会存大小端字节序呢?
大小端的来由主要是多个字节单位的数据类型单元需要约定在内存如何存放,如32位Int整型为四个字节,然后计算机存储与读取数据最小单位是Byte(一个字节,8个Bit),故32位四个字节的整型就需要分四个单玩按规定的顺序放置到内存中。目前是存在两种存放的规侧:分别是大小端字节序,如下是示图:
【基础知识系列】用示例一窥字节序-大小端_第7张图片

什么是大端字节序?
比较符合人类阅读习惯的字节序为大端序,是从左到右扫描,看到的多字节的数据类型(如32位整型),每个字节单位是从大到小的排列,非常直观,符合人类的直觉感观(这里的大是指高位字节,小是指低位字节),即字节单元从大到小的排列,就是高位字节数排在内存的最前(存诸在内存的低地址位)低位节数排到后面(低字节存储在内存的高地址位)。内存在横向空间/左到右是低位地址到高位地址空间来分布!

什么是小端字节序?
主机/计算机字节序通常是小端,有些主机同时支持大小端字节序,通道配置开关指定当前支持大端还是小端
为方便计算机存储处理的字节序为小端序,也是说从左到右扫描,看到的多个字节的数据,每个字节单位是倒着排序的,从小到大的排列;低位字节存放在内存的前面(内存的低地位),高位字节存放在内存的后面(内存的高地位)

什么是网络字节序?
网络字节序是网络上传输所约定的统一的字节序,便于不同字节序的主机交换数字。网络字节序是大端序,即网络过来的字节顺需要通过字节转换接口换为主机序,然后当主机序数据发送到网络时也需要转换为网络序。
注意:
1、只有多字节单位的数据类型才需要做字节序的转化,如char、byte或char、byte数据这类是一个字节单位的就无须关注与处理;
2、字节序转接接口是没有副作用的,即当主机序也是大端序时,调用网络序化主机序的接口时,内部是没有做任何处理的( 即接口内部判断逻辑,如果当前主机序是大端就不需要做任何的转化操作)
【基础知识系列】用示例一窥字节序-大小端_第8张图片

相关文章

  • 阮一峰老师的文章《理解字节序》
  • man7-字符序转化的接口
  • porting-your-macos-apps-to-apple-silicon 提到mac的byte order
  • 计算机网络——网络字节序(大端字节序(Big Endian)\小端字节序(Little Endian))
  • 本地字节序和网络字节序的区别是什么?

你可能感兴趣的:(基础知识,C/C++,byte-oder,大小端,字节序,Little-Endian,Big-Endian)