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

代码示例

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

mac 环境示例

代码

#include <iostream>

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;
}

运行结果

在这里插入图片描述

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

PS: 苹果官网文档也有说明的,MAC电脑,包括最新出M1、M2 都是小端序
在这里插入图片描述

运行时内存

使用Clion IDE的Memory View功能!
在这里插入图片描述
如下是上述代码示例中x变量在内存中的存储情况
在这里插入图片描述

Android环境示例

代码

native-lib.cpp文件的内容

#include <jni.h>
#include <string>
#include <android/log.h>

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());
}

运行结果

在这里插入图片描述
结论:Linux/Android 系统 的主机字节序是小端/little-endian

运行时内存

PS: 使用AS的Memory View功能!
在这里插入图片描述

大小端 big/little enidan

为什么会存大小端字节序呢?
大小端的来由主要是多个字节单位的数据类型单元需要约定在内存如何存放,如32位Int整型为四个字节,然后计算机存储与读取数据最小单位是Byte(一个字节,8个Bit),故32位四个字节的整型就需要分四个单玩按规定的顺序放置到内存中。目前是存在两种存放的规侧:分别是大小端字节序,如下是示图:
在这里插入图片描述

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

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

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

相关文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值