大小端字节序详解

简介: 在开始正文之前,我想先问一下大家,内存中是怎样存放一个数的?当然啊,我这里问的不是数据存储的形式(比如整数存原码,负数存补码),而是一个数据存放的顺序 我们先看下面这个例子,当我们看看当把十六进制函数0x11223344存进内存中会是怎么样的。

引文

   在开始正文之前,我想先问一下大家,内存中是怎样存放一个数的?当然啊,我这里问的不是数据存储的形式(比如整数存原码,负数存补码),而是一个数据存放的顺序

  我们先看下面这个例子,当我们看看当把十六进制函数0x11223344存进内存中会是怎么样的。

  我们看这个数低位44,高位33,再高位22,再高位11(注意44 、33、22、11各占一个字节,44地址0x0078F20,33地址...21,22地址...22,11地址...23),而我们看到这个数在内存中是倒着放的。为什么呢?接下来我讲引入大小端概念,为大家解答。

6c10c3963f710abbc418fcc5f317b560_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aiB5aiB5rKB5rKB,size_20,color_FFFFFF,t_70,g_se,x_16.png

大小端介绍

(1)什么是大端小端

       大小端全称大小端字节序存储,分为大端字节序存储和小端字节序存储。为什么叫字节序呢?就是以字节为单元来排它的循序

在学习大小端存储之前,我们必须了解几个概念,

(1)我们要知道一个十六进制位能转换4个二进制位,那两个十六进制位就能转换8个二进制位,也就是一个字节(11 、 22 、 33 、44)。

(2)其中44是a中最低位的一个数据,11是a中最高位的一个数据

在内存中,a有两种存储方式。

       当我们把低位字节处的数据(44)放到高地址置处,把高位字节处的数据(11)放到低地址处,这种存储方式就是大端存储反之就是小端存储

如下图所示

大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中。

小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中。

(2)为什么有大端和小端

   为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元 都对应着一个字节,一个字节为8 bit

但是在C语言中除了8 bit的char之外,还有16 bit的short型,32 bit的long型(要看具体的编 译器),另外,对于位数大于8位 的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如 何将多个字节安排的问题。

    因此就 导致了大端存储模式和小端存储模式。

例如:

      一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 ,x 的值为 0x1122 ,那么 0x11 为 高字节, 0x22 为低字节。对于大端 模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22 放在高地址中,即 0x0011 中。

小端模式, 刚好相反。

        我们常用的 X86 结构是小端模式,而 KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以 由硬件来选择是大端模式还是小端 模式。

(3)笔试题讲解

请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前机器的字节序。(10分)

这是2015百度系统工程师笔试题,第一问咱们已经所过了,忘记的小伙伴可以回去再看一遍。


第二问我们可以用C语言来判断机器的大小端字节序。


   首先我们知道一个数在内存中存储是第一个字节的数不相同,所以我们只需要判断内存中第一个字节就能判断大小端字节序。


   我们先定义一个变量并赋值为1(1比较容易判断),1的十六进制位0x00000001,所以我们能判断00为大端字节处数据,01为小端字节处数据


如下在内存中的两种存储方式,如果我们那第一个字节是0那就是大端,如果是1那就是小端。

e2b1726924cb8250a9749e0b09dfe401_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aiB5aiB5rKB5rKB,size_20,color_FFFFFF,t_70,g_se,x_16.png

问题已经分析完了,接下来就该实现代码了。但是我们如果在四个字节里面取一个字节呢?


不知道大家了解char*字符型指针吗,char*指针解引用访问一个字节,我们可以借此把a的地址强制转换成char*保存在一个char*指针,解引用指针就能取出第一个字节了。


代码实现如下:

#include<stdio.h>
int main()
{
  int a = 1;
  //000000000000000000000001
  //0x 00 00 00 01
  char* p = (char*)&a;
  if (*p == 1)
  {
  printf("小端\n");
  }
  else {
  printf("大端\n");
  }
  return 0;
}

5306b81978cfc1bdeaffda4a2689c317_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aiB5aiB5rKB5rKB,size_20,color_FFFFFF,t_70,g_se,x_16.png


到此本题结果就出来了。但是对我们来说得出结果还没有结束,我们需要等优等的代码。


首先这个代码是一次性的呀,如果别人想用的话就用不了了,所以我们可以把大小端判断代码封装成一个函数,这样别只要调用函数就能知道电脑是大端还是小端了。


同时我们最后不要在函数内打印,因为我们也不知道别人是否要打印结果,所以我们可以返回1代表是小端,返回0代表是大端。

到这有人可能发现了,这个代码还可以再简化一下。我们看*p,如果*p为1就返回1,那我们何不就返回*p呢,而*p是从那个地方获取的值呢?是*(char*)&a


所以我们直接return *(char*)&a

到此代码优化就完毕了。

int check_sys()
{
  int a = 1;
  char* p = (char*)&a;
  if (*p == 1)
  {
  return 1;//小端
  }
  else {
  return 0;//大端
  }
}
int check_sys()
{
  int a = 1;
  return *(char*)&a;
}


以上就是大小端字节序的讲解,有错误的地方希望大家能批评指正,别忘了点赞👍+收藏⭐️哦  


相关文章
|
4月前
|
存储
计算机存储,字节分为大端和小端
计算机存储,字节分为大端和小端
35 1
|
3月前
|
存储 网络协议 API
大端与小端概念、多字节之间与单字节多部分的大小端转换详解
大端与小端概念、多字节之间与单字节多部分的大小端转换详解
63 1
|
7月前
|
存储 小程序 编译器
C语言:大小端字节序存储
大端字节序存储模式:把一个数据低位字节处的数据存放在高地址处,数据高位字节处的数据存放在低地址处
59 0
|
8月前
|
存储 编译器 C语言
大小端字节序和整型提升
大小端字节序和整型提升
|
10月前
|
存储 编译器 C语言
【大小端问题】
大小端是什么? 计算机在内存存储中有两中存储模式: 大端字节序存储模式和小端字节序存储模式。 大端存储模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中。 小端存储模式,是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中。
|
11月前
|
存储 C语言
【C语言】大小端字节序问题
一、大小端字节序问题 大小端是由CPU决定的,大小端可以理解为字节顺序,所以大小端全称叫大端字节序、小端字节序。其实大端、小端这两个词是从《格列佛游记》里出来的。《格列佛游记》有一段讲的是吃鸡蛋是从大的那头敲开还是小的那头敲开的问题,书中把从大头敲开的那种叫做大端,把从小头敲开的那种叫小端,第一个指出计算机数据存储顺序问题的人就采用了这个大小端的说法。
|
11月前
|
存储 网络协议 编译器
字节序,主机字节序与网络字节序
是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。在计算机中是以字节为单位,每个地址对应一个字节,一个字节8bit。在C中,除了8bit的char以外,还有16bit的short,32位的int,64位long,当然具体要由编译器决定,可以通过sizeof来获取不同类型在内存中占用的字节数。在计算机系统中,当物理单位的长度大于1个字节时(所以char数据就不用区分字节序),就要区分字节顺序。常见的字节顺序有两种:大端和小端,当然还有其他字节顺序,但不常见,例如Middle Endian,通俗的讲,字节序就是cpu对内存中进行存储的顺序(以字节为单位进行存取)
137 0
|
存储 编译器 C语言
|
存储
理解字节序
计算机硬件有两种储存数据的方式:**大端字节序**(big endian)和**小端字节序**(little endian)
65 0