大小端字节序详解

目录

引文

大小端介绍

(1)什么是大端小端

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

(3)笔试题讲解


引文

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

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

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

大小端介绍

(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那就是小端。

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

不知道大家了解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;
}

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

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

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

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

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

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

int check_sys()
{
	int a = 1;
	return *(char*)&a;
	
}

到此代码优化就完毕了。

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

      😜  关注我!带来等多精彩🎉🎉

  • 14
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱躺平的威威

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值