一起talk C栗子吧(第一百五十二回:C语言实例--计算机中的大小端)

各位看官们,大家好,上一回中咱们说的是socket通信地址的例子,这一回咱们说的例子是:计算机中的大小端 。闲话休提,言归正转。让我们一起talk C栗子吧!

大小端据说来源于小说《格列佛游记》,书中说:人们在争论打开鸡蛋的方式是从鸡蛋的大端还是小端打开鸡蛋。争论不休,甚至还引起了战争。你说说,不管你从哪一端打开鸡蛋,打开的都是鸡蛋呀,这有什么可以争论的呢?还要通过战争来解决。大家不必关注这个争论,如果真想了解其中的细节,可以看看这部小说。不过在计算机中的大小端就不像小说中争论打开鸡蛋那么简单了,因为它有着不同的意义。

大小端表示字节在计算机中存储顺序。它是从英文Big endian和Little endian翻译过来的。我们使用的大部分数据存储在多个字节中,这些字节的排列顺序有一定排列规则:

  • 当计算机使用大端方式存储数据时,字节的排列顺序是从高位到低位。
  • 当计算机使用小端方式存储数据时,字节的排列顺序是从低位到高位。

这么说,大家可能觉得很抽象,接下来我们通过具体的例子来说明什么是大小端。例如:计算机内存中的某个数值:0x12345678。其中1表示高位,8表示低位。

  • 当计算机使用大端来存储该数据时,那么该数据在计算机中的存储方式是:0x12345678。
  • 当计算机使用小端来存储该数据时,那么该数据在计算机中的存储方式是:0x87654321。

这时有看官提问了:我们平时写程序时也没有体会到大小端有什么不同呢?其实,这不怪大家,因为我们目前使用的个人计算机中绝大部分是X86架构的计算机,该架构类型的计算机都使用小端方式来存储数据。这也就是说大家都在使用同一种存储数据的方式,所以体会不到数据存储的差异。在一些大型服务器中会使用大端方式存储数据的计算机,这类型机器,我们很少能接接触到。大家如果不清楚自己使用的计算机属于大小端中的哪一种,我们可以使用代码来判断。

#include <stdio.h>

int main()
{
    int a = 0x12345678;
    int len = sizeof(int); // get the count of byte
    int i =-0;
    char *p = (char*)&a;

    printf(" [address] [value] \n");
    while(i<len)
    {
        printf("[%p] [%x] \n",p+i,*(p+i));
        i++;
    }
    return 0;
}

在代码中我们把十六进制的数据赋值给了一个int型变量,之所以使用十六进制的数值,是为了输出该数值时方便观察。大家都知道计算机中使用多个字节存储int型变量,使用单个字节存储char型变量,因此,我们把int类型变量的地址强制转换为char类型的指针,这样可以按照字节的方式来查看int型变量的存储细节。这些细节包含:

  • int型变量的字节数量;
  • 多个字节的存放顺序;
  • 每个字节中存储的数据。

下面是程序的运行结果,请大家参考:

 [address]   [value] 
[0xbfe7a880]   [78] 
[0xbfe7a881]   [56] 
[0xbfe7a882]   [34] 
[0xbfe7a883]   [12]

从上面的程序运行结果中可以看到,int型变量使用四个字节来存储数据,这四个字节的地址从0x0xbfe7a880到0xbfe7a883依次排列,其中低地址0xbfe7a880存储低位数据78,高位地址0xbfe7a883存储高位数据12。大家结合我们上面的介绍,可以看到,该计算机使用的是小端方式存储数据。

看官们,除了部分使用大端的计算机外,网络通信中使用的套接字使用大端方式传输数据,这也是我们在介绍套接字的过程中专门插入一个章回来介绍大小端的原因。大家都知道,我们的计算机中使用小端方式存储数据,如果使用网络通信时需要使用大端方式来传输数据。这显然是有差异的,如何处理存储方式上的差异呢?我们在后面章回中会做详细的介绍。

各位看官,关于计算机中大小端的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解 。

你可能感兴趣的:(socket,大小端)