弄懂大端小端含义

  • Post author:
  • Post category:其他

现在先来理解这对概念,大端和小端这两个令人迷惑的术语究竟是如何产生的?《程序设计实践》第9章中提到,“大端”和“小端”可以追溯到1726年的Jonathan Swift的《格列佛游记》,其中一篇讲到有两个国家因为吃鸡蛋究竟是先打破较大的一端还是先打破较小的一端而争执不休,甚至爆发了战争。1981年10月,Danny Cohen的文章《论圣战以及对和平的祈祷》(On holy wars and a plea for peace)将这一对词语引入了计算机界。这么看来,所谓大端和小端,也就是big-endian和little-endian,其实是从描述鸡蛋的部位而引申到计算机地址的描述,也可以说,是从一个俚语衍化来的计算机术语。稍有些英语常识的人都会知道,如果单靠字面意思来理解俚语,那是很难猜到它的正确含义的。在计算机里,对于地址的描述,很少用“大”和“小”来形容;对应地,用的更多的是“高”和“低”;很不幸地,这对术语直接按字面翻译过来就成了“大端”和“小端”,让人产生迷惑也不是很奇怪的事了。

(这段文字是《UNIX网络编程·卷一》的关于这个概念的概括;不仅限于这本书,很多计算机书籍都是这么介绍这个概念的,你会在和计算机相关不同领域的书中遇到它们。

  对于一个由2个字节组成的16位整数,在内存中存储这两个字节有两种方法:

一种是将低序字节 存储在 起始地址(低地址),这称为小端(little-endian)字节序;(简记 低低小)

另一种方法是将高序字节 存储在起始地址(低地址),这称为大端(big-endian)字节序

图的特别说明:

要注意的是 图中 为了清晰的表达出 MSB, LSB  的概念,其中我们在书写时 一定要注意 符合c中的习惯(低地址 –>  高地址)!!! 举例来说:

在表示一个 字符串 和 数组时  都是 低地址 —>高地址 这样表示 ,(怎么验证呢 指针 +1 看下一位一定是 在 右边)

所以,在书面表示大小端时一定要符合书面表达的习惯,在UTF的编码中 里边涉及的 大小端的 表示方法 也是 符合 这个习惯的(低地址 —> 高地址)

在图中,顶部表明内存地址增长方向从右到左,在底部标明内存地址增长的方向为从左到右。并且还标明最高有效位(most significant bit,MSB)是这个16位值最左边一位,最低有效位(least significant bit, LSB)是这个16位值最右边一位。术语“小端”和“大端”表示多个字节值的哪一端(小端或大端)存储在该值的起始地址。

  这两种字节序没有标准可循,都有系统在使用。把某个给定系统所用的字节序称为主机字节序,可以用以下程序输出主机字节序。方法是在一个短整数变量中存放2字节的值0x0102,然后查看它的连续字节c[0](对应上图地址A)和c[1](对应上图地址A+1),以此确定字节序。

#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
    union {
        short s;
        char c[sizeof(short)];
    } un;
    un.s = 0x0102;
    if(sizeof(short)==2) {
        if(un.c[0]==1 && un.c[1] == 2)
            printf("big-endian\n");
        else if (un.c[0] == 2 && un.c[1] == 1)
            printf("little-endian\n");
        else
            printf("unknown\n");
    } else
        printf("sizeof(short)= %d\n",sizeof(short));
    exit(0);
}

0x0102

二进制表示(书面表示): 00000001  00000010                #地址  高位 —>  低位

小端(即小端书面表示):            00000010  00000001      #地址   低 —>  高

大端 (即大端书面表示):           00000001  00000010      #地址   低 —-> 高

un.c[0] – –  un.c[1]        #地址  低 —>  高    2 ——-   1    小端

un.c[0] – –  un.c[1]        #地址  低 —-> 高   1 ——     2    大端

注意 大小端的 概念:是说的  字节序,最小单位是 字节 ,对单个字节 如cha b;是 无意义的,只有是表示数字需要大于1个字节存储时,才有的大小端之区分。

但是,一个字节里(8bit) 也是高位 和低位,像 就一个字节 如 char  也是数字,既然能被解释为数字,他就必须区分出 高位 和 地位

结论: 大端表示 法 和  书写(整型的二进制书写)时 的 顺序一致!

或者程序二:

#include <stdio.h>

int main()

{

     union
        {
            int i;
            char c;

        }u;

    u.i = 1;

    printf("当前计算机:%s\n",u.c == 1? "小端" : "大端");
    return 0;
}

代码三:php代码判断:

$tmp = unpack('S', "\x01\x00"); //   字符串 地址 低 ---->  高

var_dump($tmp);
var_dump($tmp[1]);
var_dump($isLittleEndian = $tmp[1] === 1);

/*
array(1) {
  [1]=>
  int(1)
}
int(1)
bool(true)
*/

网络字节序是:大端。


版权声明:本文为u013862108原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。