字节序问题

字节序问题

常用术语

网络字节序:network byte order

主机/本地字节序:host byte order

大端字节序:big endian

小端字节序:small endian

什么是大端/小端字节序呢?

先理解什么是高位什么低位.

假设一个变量a = 0xdeadbeef,那么如果按照字节的位数来理解的话,左边就是高位,右边就是低位,可能还比较模糊,比如我们说这里有1000个苹果(十进制),那么从左边的1开始就是高位,右边就是低位,因为最左边的1实际上代表的是一千个最左边的1.这个规律适用于所有数制.

好了,现在可以说大端小端了.

大端就是低位对低位,高位对高位,与我们人类的常识中对数字的理解是一致的.这是什么意思呢? 数字中的低位对应低位的地址,数字中的高位对应高位的地址. 还是a = 0xdeadbeef ,

地址 变量a
0x00地址中的低位,低是小的意思 0xef
0x01 0xbe
0x02 0xad
0x03地址中的高位 0xde

小端则与大端完全颠倒,低位对高位,高位对低位.

需要注意的是,只是字节的顺序颠倒了,而字节中的二进制位是不变的,这也是为什么叫做字节序而不是"位序"的原因

网络字节序与主机字节序

网络字节序就是大端字节序

主机根据不同的机器会有不同的结果,可能是大端,也可能是小端,但是以小端更为普遍.

实践测试

环境: centos7 64

代码:

#include <stdio.h>
#include <arpa/inet.h>


#define TRUE    0
#define FALSE   -1

int is_small_endian(void)
{
    uint32_t t = 0xdeadbeef;
    uint8_t* p = (uint8_t*)&t;
    
    if(*p == 0xef)return TRUE;
    else if(*p == 0xde)return FALSE;
}


int main()
{
    uint32_t a = 0xdeadbeef;
    printf("a: 0x%08x\n",a);

    if(is_small_endian()==TRUE)printf("small endian\n");
    else printf("big endian\n");

    //if the machine is little end,then 'a' will be reversed by bytes
    uint32_t net_a = htonl(a);
    printf("net_a: 0x%08x\n",net_a);

    uint32_t net__to_local_a = ntohl(a);
    printf("net_to_local_a: 0x%08x\n",net__to_local_a);

    return 0;
}

结果:

a: 0xdeadbeef
small endian
net_a: 0xefbeadde
net_to_local_a: 0xefbeadde

一个有趣的现象

ntohl(123)与htonl(123)的结果是一样的,无论其主机字节序是什么.

如果主机字节序是小端,那么ntohl(123)将是123的大端字节序
如果主机字节序是大端,那么ntohl(123)将是123的大端字节序

从这里可以推测ntohl(),htonl()函数的逻辑,先判断主机的字节序,如果是小端,那么就翻转;如果是大端,那么就保持不变
posted @ 2020-02-11 09:43  virgil_devil  阅读(382)  评论(0编辑  收藏  举报