CPU存储方式:大小端判断的三种方法

基本概念

  在这里简单的记录和介绍下大小端模式,如果在以后使用的过程中遇到更为深层次的问题再做讨论。

名词注释
大端 较低 的有效字节存放在 较高 的存储器地址
较高 的有效字节存放在 较低 的存储器地址
小端 较低 的有效字节存放在 较低 的存储器地址
较高 的有效字节存放在 较高 的存储器地址

存储方式

  如何去理解这个概念,我们要回到代码当中,通过变量的存储方式去判断,不妨先定义一个无符号整型数据 :

unsigned int data = 0x12345678;

  虽然在这里我们并未验证32位数据在Little-endian/Big-endian模式下内存中存放的方式究竟如何,但通过概念可以大致得出以下图示,稍后会通过代码去验证其表示方式是否正确。

大端内存地址小端
0x780x40030x12
0x560x40020x34
0x340x40010x56
0x120x40000x78

三种方式判断编译器的大小端

1、通过移位操作判断(待验证)
  此验证方法由于需要大端和小端两种不同编译器环境去验证才可确保其真实性,但我恰好没有(太懒了,下次一定做),这是一种通过移位操作判断大小端的方法,但这种方法可能会无效,想了解的可以看一下,否则直接略过即可。
  
  理由如下:因为大小端是数据在内存中的字节存放顺序,而运算指令是由CPU执行的,运算等方法是改变CPU寄存器中所存的值,而寄存器中的值通过大小端模式已经得到了正确的数据存放顺序,也就是说移位操作是针对数据而执行的,与数据存储方式无关,故不能通过移位操作判断数据存储方式。

地址: 高地址 ------------------> 低地址
小端模式存放:0000 0001 >> 1 == 0000 0000
大端模式存放:1000 0000 >> 1 == 0100 0000

  在这里,还是贴出相关的判断代码,因为其仅需一句宏即可完成,n为int型变量,数值为1。

ifndef TRUE
#define TRUE 1
#endif
ifndef FALSE
#define FALSE 0
#endif
#define check_big_endian(n)		n>>1?TRUE:FALSE

2、通过联合体判断
  在使用联合体前,首先介绍下联合体的特点,简单的说就是一段空间,大家一起使用不分你我,主要作用是节省内存,跟结构体最大的区别是结构体内变量的空间是独立的,而联合体是共用同一段内存,利用这个特性,除了节省空间外,还能用于机器大小端的判断。

联合体特点
union中可以定义多个成员,union的大小由最大的成员的大小决定
union成员共享同一块大小的内存,一次只能使用其中的一个成员
对某一个成员赋值,会覆盖其他成员的值
联合体union的存放顺序是所有成员都从低地址开始存放

  利用联合体共用同一段内存的特性,申请一段大小为4个字节的空间,然后根据一个16进制占4位(bit),两个16进制占8位(bit)共1字节的原理,用0x12345678共8个16进制将联合体内的4个字节全部填充完整,最后直接取第一个字节的值,即取较低地址当中的值,根据我们上述说的小端模式中:较低的有效字节存放在较低的存储器地址,可知较低的有效字节为:0x78,如果该地址存放的值恰好等于0x78,那么即为小端模式,如果等于0x12,则为大端模式。

BOOL check_little_endian()
{
	union
	{
		char a;
		int  b;

	}u;

	u.b = 0x12345678;

	return (BOOL)(u.a == 0x78);
}

3、通过强制类型转换判断
  当我们明白联合体的工作原理后,理解类型强制转换的方法应该是水到渠成了,同样是定义一个int型数据,取该数据的地址,然后用char*指针指向该地址的第一个字节,随后读取char *指针指向地址中所存储的值,如果为0x78,则是小端模式,如果为0x12,则是大端模式。

uint32 check_little_endian()
{
	int i = 0x12345678;

	char *p = (char *)&i;

	return (*p == 0x78);
}

参考:大小端模式以及两种判断方法

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
注:分卷一的说明写错了,总共三卷压缩包 Visual C++通用范例开发金典(附光盘)/开发专家 (分卷二/共三卷) 【作者】: 韦朴 陈泰生 【出版日期】:2008-06 【出版社】:电子工业出版社 【所属分类】: 图书 > 工业技术 【所属分类】: 图书 > 计算机与网络 > 程序语言与软件开发 【附属物】:光盘1张 【总 页 数】:631 【产品条码】:9787121065675 【语 种】:汉 【装  帧】:平装 【开  本】:259mmX184mm 【丛书名】:开发专家 【适合年龄群】:青年(14-20岁),研究人员,普通成人 【关键字】:C语言//程序设计 【首印年月】:2008-06 【本版年月】:2008-06 【本次出版年月】:2008-06 【版次印次】:第1版第1次 【简介】    Visual C++是Microsoft公司开发的可视化软件开发工具,具有简单、高效、功能强大等特点,是Windows环境下优秀的程序设计工具之一。本书系统全面地介绍了Visual C++软件——Microsoft Visual C++6.0的具体使用方法和操作技巧。全书按照Visual C++的实际应用共分为11章,主要内容包括:用户界面设计、文档应用程序设计、图形程序设计、文件I/O与串行化程序设计、多媒体程序设计、系统控制与注册表、数据库技术程序设计、网络、通信技术程序设计、打印程序设计、线程和进程程序设计、动态链接库和ActiveX控件等。    本书是各级程序开发人员的必备参考书,同时也非常适合大中专院校师生阅读。此外,本书也非常适于作为各类培训班的培训教程。 【目录】   第1章 用户界面设计    1.1 常用控件程序设计    1.1.1 静态控件和按钮范例    1.1.2 编辑框和旋转按钮控件范例    1.1.3 列表框控件范例    1.1.4 进展条、滚动条和滑动条控件范例    1.1.5 Tab控件、时间控件、列表控件和树控件范例    1.2 对话框程序设计    1.3 本章小结   第2章 文档应用程序设计    2.1 菜单程序设计    2.1.1 静态菜单设计    2.1.2 动态菜单设计    2.2 工具栏和状态栏程序设计    2.2.1 窗口外观修改    2.2.2 工具栏和状态栏    2.3 文档与视图程序设计    2.3.1 基于文本的编程    2.3.2 框架窗体的编程    2.4 本章小结   第3章 图形程序设计    3.1 基本图形绘制    3.1.1 简单直线的绘制    3.1.2 画刷    3.1.3 复杂图形的绘制    3.1.4 文本绘制    3.2 图像操作    3.2.1 图像显示    3.2.2 图像效果变化    3.2.3 图像基本操作    3.3 3D图形的绘制    3.4 本章小结   第4章 文件I/O与串行化程序设计    4.1 文件基本操作    4.1.1 文件的读、写操作    4.1.2 文档与串行化    4.2 高级文件操作    4.2.1 文件的删除与搜索    4.2.2 文件夹和文件目录    4.3 本章小结   第5章 多媒体程序设计    5.1 多媒体音频操作    5.2 多媒体视频操作    5.3 本章小结   第6章 系统控制与注册表    6.1 注册表相关操作    6.1.1 注册表的读取与写入    6.1.2 注册表的备份    6.1.3 注册表的恢复    6.1.4 设置注册表键值    6.1.5 删除子键    6.1.6 注册表枚举函数    6.2 系统控制    6.2.1 隐藏、显示文件    6.2.2 隐藏、显示文件夹    6.2.3 隐藏“我的电脑”    6.2.4 隐藏驱动器    6.2.5 隐藏“回收站”    6.2.6 隐藏“我的文档”    6.2.7 隐藏桌面上的所有图标    6.2.8 隐藏任务栏    6.2.9 禁用注册表    6.2.10 关闭计算机    6.2.11 注销当前用户    6.2.12 设置启动自动运行程序    6.2.13 设置、显示系统当前时间    6.2.14 获取当前显示模式    6.2.15 获取操作系统版本号    6.2.16 设置桌面墙纸    6.2.17 隐式链接DLL    6.2.18 显式链接DLL    6.3 IE设置    6.3.1 修改IE标题栏    6.3.2 修改IE默认主页    6.3.3 在IE中禁止显示工具栏    6.3.4 在IE中禁止显示状态栏    6.3.5 使打开的IE窗口最大化    6.3.6 清空地址栏历史记录    6.3.7 改变收藏夹的默认路径    6.3.8 显示IE工具栏中的【字体】按钮    6.3.9 删除网页链接中的下画线    6.3.10 设置IE的缓冲区路径    6.3.11 隐藏上次登录用户的记录    6.3.12 设置域名服务器超时    6.4 系统软件信息    6.4.1 获取系统注册用户名    6.4.2 获取系统注册单位名    6.4.3 获取当前用户名    6.4.4 获取计算机名    6.4.5 获取操作系统安装序列号    6.4.6 获取操作系统的产品名称    6.4.7 获取IE的版本号    6.4.8 获取Windows的版本号    6.4.9 获取Windows的内建号    6.4.10 获取Windows的版本名称    6.4.11 获取临时文件夹的位置    6.4.12 获取“桌面”文件夹的位置    6.4.13 获取字体文件夹的位置    6.4.14 获取“网上邻居”文件夹的位置    6.4.15 获取“我的文档”文件夹的位置    6.4.16 获取System文件夹的位置    6.4.17 获取Windows文件夹的位置    6.5 系统硬件信息    6.5.1 获取CPU名称    6.5.2 获取CPU标识    6.5.3 获取CPU制造商名称    6.5.4 获取CPU主频    6.5.5 获取CPU个数    6.5.6 获取显卡BIOS版本号    6.5.7 获取显卡BIOS的更新日期    6.5.8 获取系统BIOS版本号    6.5.9 获取系统BIOS的更新日期    6.6 存储设备管理    6.6.1 获取磁盘序列号    6.6.2 获取磁盘卷标名称    6.6.3 设置磁盘卷标名称    6.6.4 获取磁盘容量大小    6.6.5 获取磁盘剩余容量大小    6.6.6 获取磁盘“文件系统”名称    6.6.7 获取系统所有的磁盘驱动器    6.6.8 判断磁盘驱动器类型    6.7 本章小结   第7章 数据库技术程序设计    7.1 数据库的连接和遍历    7.1.1 数据库的连接    7.1.2 数据库的遍历    7.2 数据查询技术    7.2.1 基本查询    7.2.2 以时间为基础的查询    7.2.3 模糊查询    7.2.4 条件查询    7.2.5 统计汇总查询    7.2.6 分组查询    7.2.7 查询的排序    7.2.8 连接查询    7.2.9 子查询技术    7.2.10 合并查询    7.2.11 控件查询技术    7.3 数据的删除与更新    7.3.1 数据删除    7.3.2 数据更新    7.4 本章小结   第8章 网络、通信技术程序设计    8.1 基本网络操作    8.1.1 本地信息操作    8.1.2 获取网络信息    8.2 高级网络操作    8.3 基于串口的通信    8.4 本章小结   第9章 打印程序设计    9.1 基本打印操作    9.1.1 打印的基本框架    9.1.2 单文档打印    9.1.3 对话框打印    9.2 打印控制    9.2.1 打印参数获取    9.2.2 打印参数设置    9.3 本章小结   第10章 线程和进程程序设计    10.1 线程的创建和终止    10.2 线程同步    10.3 进程间通信    10.4 本章小结   第11章 动态链接库和ActiveX控件    11.1 动态链接库    11.2 ActiveX控件    11.3 本章小结   索引   参考文献
注:第一卷的描述写错了,总共是三卷压缩包 Visual C++通用范例开发金典(附光盘)/开发专家 【作者】: 韦朴 陈泰生 【出版日期】:2008-06 【出版社】:电子工业出版社 【所属分类】: 图书 > 工业技术 【所属分类】: 图书 > 计算机与网络 > 程序语言与软件开发 【附属物】:光盘1张 【总 页 数】:631 【产品条码】:9787121065675 【语 种】:汉 【装  帧】:平装 【开  本】:259mmX184mm 【丛书名】:开发专家 【适合年龄群】:青年(14-20岁),研究人员,普通成人 【关键字】:C语言//程序设计 【首印年月】:2008-06 【本版年月】:2008-06 【本次出版年月】:2008-06 【版次印次】:第1版第1次 【简介】    Visual C++是Microsoft公司开发的可视化软件开发工具,具有简单、高效、功能强大等特点,是Windows环境下优秀的程序设计工具之一。本书系统全面地介绍了Visual C++软件——Microsoft Visual C++6.0的具体使用方法和操作技巧。全书按照Visual C++的实际应用共分为11章,主要内容包括:用户界面设计、文档应用程序设计、图形程序设计、文件I/O与串行化程序设计、多媒体程序设计、系统控制与注册表、数据库技术程序设计、网络、通信技术程序设计、打印程序设计、线程和进程程序设计、动态链接库和ActiveX控件等。    本书是各级程序开发人员的必备参考书,同时也非常适合大中专院校师生阅读。此外,本书也非常适于作为各类培训班的培训教程。 【目录】   第1章 用户界面设计    1.1 常用控件程序设计    1.1.1 静态控件和按钮范例    1.1.2 编辑框和旋转按钮控件范例    1.1.3 列表框控件范例    1.1.4 进展条、滚动条和滑动条控件范例    1.1.5 Tab控件、时间控件、列表控件和树控件范例    1.2 对话框程序设计    1.3 本章小结   第2章 文档应用程序设计    2.1 菜单程序设计    2.1.1 静态菜单设计    2.1.2 动态菜单设计    2.2 工具栏和状态栏程序设计    2.2.1 窗口外观修改    2.2.2 工具栏和状态栏    2.3 文档与视图程序设计    2.3.1 基于文本的编程    2.3.2 框架窗体的编程    2.4 本章小结   第3章 图形程序设计    3.1 基本图形绘制    3.1.1 简单直线的绘制    3.1.2 画刷    3.1.3 复杂图形的绘制    3.1.4 文本绘制    3.2 图像操作    3.2.1 图像显示    3.2.2 图像效果变化    3.2.3 图像基本操作    3.3 3D图形的绘制    3.4 本章小结   第4章 文件I/O与串行化程序设计    4.1 文件基本操作    4.1.1 文件的读、写操作    4.1.2 文档与串行化    4.2 高级文件操作    4.2.1 文件的删除与搜索    4.2.2 文件夹和文件目录    4.3 本章小结   第5章 多媒体程序设计    5.1 多媒体音频操作    5.2 多媒体视频操作    5.3 本章小结   第6章 系统控制与注册表    6.1 注册表相关操作    6.1.1 注册表的读取与写入    6.1.2 注册表的备份    6.1.3 注册表的恢复    6.1.4 设置注册表键值    6.1.5 删除子键    6.1.6 注册表枚举函数    6.2 系统控制    6.2.1 隐藏、显示文件    6.2.2 隐藏、显示文件夹    6.2.3 隐藏“我的电脑”    6.2.4 隐藏驱动器    6.2.5 隐藏“回收站”    6.2.6 隐藏“我的文档”    6.2.7 隐藏桌面上的所有图标    6.2.8 隐藏任务栏    6.2.9 禁用注册表    6.2.10 关闭计算机    6.2.11 注销当前用户    6.2.12 设置启动自动运行程序    6.2.13 设置、显示系统当前时间    6.2.14 获取当前显示模式    6.2.15 获取操作系统版本号    6.2.16 设置桌面墙纸
### 回答1: 大小端指的是数据在内存中存储的顺序,大端模式是高位字节存储在低地址,小端模式是高位字节存储在高地址。在Linux下,可以使用以下代码判断当前机器的大小端模式: ``` #include <stdio.h> int main() { unsigned int x = 0x12345678; char *c = (char*)&x; if (*c == 0x12) { printf("Big Endian\n"); } else { printf("Little Endian\n"); } return 0; } ``` ### 回答2: 在Linux中,判断系统是大端还是小端可以通过以下方法: 1. 使用C语言的方式判断:可以使用联合体的方式判断大小端。可以创建一个包含一个char类型和一个int类型的联合体,然后将这个联合体的char和int成员的值分别设置为1,然后通过判断char成员的值来确定系统的字节序。若为1,则为小端;若为0,则为大端。 ```c #include <stdio.h> int main() { union { char c; int i; } endian; endian.i = 1; if (endian.c == 1) { printf("小端字节序\n"); } else { printf("大端字节序\n"); } return 0; } ``` 2. 使用命令行工具:在Linux终端中使用命令`lscpu`可以获取CPU的详细信息,其中有一项是"Byte Order",如果显示为"Little Endian"则表示是小端字节序,如果显示为"Big Endian"则表示是大端字节序。 综上所述,以上两种方法都可以在Linux中判断大小端。 ### 回答3: 在Linux中,可以通过以下方法判断当前系统的字节序是大端(Big Endian)还是小端(Little Endian)。 方法一:使用C语言编写一个小程序进行判断。 ```c #include<stdio.h> int main() { unsigned int num = 1; char *p = (char *)&num; if (*p == 1) { printf("该系统为小端字节序\n"); } else { printf("该系统为大端字节序\n"); } return 0; } ``` 该程序定义了一个无符号整型变量`num`并给其赋值为1,然后通过指针`p`来指向`num`的地址。由于整型在内存中是以字节的形式存储的,我们将首地址的字节与1进行比较,如果相等,则说明是小端字节序,否则为大端字节序。 方法二:使用命令行查看系统的字节序。 在Linux中,我们可以通过命令`lscpu`来查看系统的相关信息,其中包括字节序。在终端中输入如下命令: ``` lscpu | grep "Byte Order" ``` 如果输出结果为`Byte Order: Little Endian`,则说明系统为小端字节序。如果输出结果为`Byte Order: Big Endian`,则说明系统为大端字节序。 以上两种方法可以帮助我们在Linux中判断大小端

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值