《C/C++ 面试 100 例》(十)字节序

本文深入解析字节序概念,区分大端序与小端序,探讨其在内存中的存储方式。同时,文章介绍了主机字节序与网络字节序的区别,并提供了字节序转换的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

字节序

        最近在看 redis 的内存编码,里面涉及到字节序相关的内容。这里就当复习一下,做个简单的回顾。

        数据存储在内存中,是以字节为单位的,如果是单字节数据(如char、unsigned char、int8)就不会有字节序的问题。但是多字节数据(如 int、float、double)就要考虑字节序的问题了。字节序共分为两种:大端序 和 小端序。

大端序

        数据的高位字节存储在地址的低端;低位字节存储在地址的高端。如图所示,值为 0x12345678 的四字节整数在大端序的主机上的内存排布。

小端序

        数据的高位字节存储在地址的高端;低位字节存储在地址的低端。如图所示,值为 0x12345678 的四字节整数在小端序的主机上的内存排布。

主机字节序和网络字节序

         除了主机字节序,还有网络字节序。主机字节序由CPU决定,Intel Core 经测试都是小端字节序。而网络字节序采用的是大端序。测试字节序可以通过一段 C 的源码搞定。

#include <stdio.h>

int main(int argc, char *argv[]) {
    int i;
    int x = 0x12345678;
    for (i = 0; i < sizeof(int); ++i) {
        unsigned char *p = ((unsigned char *)(&x)) + i;
        unsigned char v = *p;
        printf("%p 0x%d%d\n", p, v>>4, v & 0xf );
    }
    return 0;
}

         取得整数 x 的首地址转换成 unsigned char* 指针后再向前偏移 i 个单位,分别得到这 sizeof(int) 个字节的地址,然后用 * 取得每个地址上的值,通过位运算转换成 16进制 输出。
         Linux 系统可以通过指令获取 CPU 的类型:

cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
4  Intel(R) Core(TM) i3-2120 CPU @ 3.30GHz

大端序和小端序的互转

        大端序和小端序的互相转换,其实就是内存翻转,在知道一个整数或者一个指针的字节数的时候,就是做一个镜像的交换。这里以 64位 整型为例:

void memrev64(void *p) {
    unsigned char *x = p, t;

    t = x[0];
    x[0] = x[7];
    x[7] = t;
    t = x[1];
    x[1] = x[6];
    x[6] = t;
    t = x[2];
    x[2] = x[5];
    x[5] = t;
    t = x[3];
    x[3] = x[4];
    x[4] = t;
}

uint64_t intrev64(uint64_t v) {
    memrev64(&v);
    return v;
}

        64位整数的字节数为8,所以在字节序进行转换的时候:
        第0个字节和第7个字节交换;
        第1个字节和第6个字节交换;
        第2个字节和第5个字节交换;
        第3个字节和第4个字节交换;
        对于 32位整数、16位整数的情况,就更加简单了,不再累述。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英雄哪里出来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值