c: 关于大小端存储

参考:
《大小端(数据在内存中的存储)》
《细说ASCII、GB2312/GBK/GB18030、Unicode、UTF-8/UTF-16/UTF-32编码》
《终极二进制分析TCP协议通信的过程和字段含义》

一、什么是大小端存储?

  • 大端(存储)模式:是指一个数据的低位字节序的内容放在高地址处,高位字节序存的内容放在低地址处。
  • 小端(存储)模式:是指一个数据的低位字节序内容存放在低地址处,高位字节序的内容存放在高地址处。(可以总结为“小小小”即低位、低地址、小端)

二、涉及到大小端场景

2.1 int等类型在内存中的存储

我们知道,一个int类型在内存中占用4个字节,那么这四个字节是怎样?

直接看实例:c#控制台程序,调出内存查看窗口(debug后,调试->窗口->内存->内存1):
c: 关于大小端存储_第1张图片
这就是小端存储,如果是大端存储,那么应该显示 12 34 56 78

一般CPU都是小端存储,arm的有些cpu可以切换大小端存储模式。
mac应该也是小端存储,有些地方说java是大端存储,但未验证。

2.2 网络传递

在一个TCP报文中会记录 源IP+源端口: 目标IP+目标端口,其中端口是int类型的数字,它就是大端存储:
c: 关于大小端存储_第2张图片

2.3 unicode编码

再看一个Unicode-16编码:
c: 关于大小端存储_第3张图片

注意:GBK和utf-8无大小端问题,因为它们的编码规则中指定了字节间的先后顺序

三、如何检测当前大小端

方法有很多,比如下面的(c语言):

#include 
int main()
{
    int i = 1;
    char *a = (char *)&i;
    if(*a == 1)
        printf("小端\n");
    else
        printf("大端\n");
    return 0;
}

或者(c#):

static void Main(string[] args)
{
    unsafe
    {
        int i = 0x12345678;
        byte* b = (byte*)&i;
        if ((*b).ToString("X2") == "12")
        {
            Console.WriteLine("大端");
        }
        else if ((*b).ToString("X2") == "78")
        {
            Console.WriteLine("小端");
        }
    }
}

四、其他注意项

  • 大小端是字节间的顺序,不是bit位的顺序;
  • 大小端是存储单元内字节的顺序(如:intunicode-16编码等),不是整个内容的顺序(如:一一个文本文件、一行字符串、整个tcp报文等)。

你可能感兴趣的:(c#,c/c++,其他,c#,开发语言,大小端)