c - 使用 memcpy 从数组转换为 int
问题描述
我正在尝试指针操作,并决定尝试通过使用 memcpy 从内存中直接复制来将数字数组转换为整数。
char aux[4] = {1,2,3,4};
int aux2 = 0;
memcpy((char*) &aux2, &aux[0], 4);
printf("%X", aux2);
我预计结果是 0x1020304,因为我正在将确切的字节从一个复制到另一个,但是 printf 给了我结果 0x4030201,这几乎是我想要的输出,只是向后。为什么会发生这种情况,有没有办法以“正确”的顺序获得结果?
解决方案
您的代码充其量具有实现定义的行为,并且在某些情况下具有未定义的行为。
类型int
的大小可能不同于4
: 在 16 位系统上,int
通常只有2
字节大小。您将在此类系统上具有未定义的行为。
在常规的 32 位系统上,int
有 4 个字节,但 4 个字节存储在内存中的顺序是实现定义的,称为字节序的问题:
一些系统使用大端表示,其中第一个字节是整数的最重要部分。字节
01 02 03 04
代表0x01020304
大端系统的价值,例如旧的 Mac、一些手机和嵌入式系统。相反,今天的大多数个人计算机使用little-endian表示,其中第一个字节包含整数的最低有效部分。字节
01 02 03 04
代表0x04030201
小端系统(例如您的系统)上的值。C 标准不排除其他表示形式,其中字节将按其他顺序排列。一些古老的 DEC 系统就是这种情况:PDP-11,最初开发了 C 语言(中间端或混合端)。
尽管令人惊讶,小端顺序非常合乎逻辑,因为偏移量n处的字节包含表示2 n*8和2 n*8+7之间值的位。字节顺序是一个文化问题,对于长期用户来说,这两种选择似乎都很自然。
在其他上下文中也可以找到相同的变化,例如日期组件的排序:
日本使用大端表示法:2021 年 2 月 17 日写成
2021.02.17
,欧洲使用 little-endian 表示:2021 年 2 月 17 日写成
17/02/2021
,美国使用中端表示法:2021 年 2 月 17 日写成
02/17/2021
。21 在英语中发音为21(大端),而德国人说einundzwanzig(1 和 20,小端,实际上是 3 位数字的中端)。但是 17 是17(小端),在法语中是dix-sept(大端)。
西方语言以大端格式书写数字(我今年 42 岁),但闪米特文字使用小端顺序:希伯来语(אני בת 42)和阿拉伯语(أنا ٤٢ سنة)都使用小端,因为它们是从右到左边。
这是一个更便携的版本来测试内存表示:
#include <stdio.h>
#include <string.h>
int main() {
unsigned int aux2 = 0x01020304;
unsigned char aux[sizeof(unsigned int)];
memcpy(&aux, aux2, sizeof(aux));
printf("%X is represented in memory as", aux2);
for (size_t i = 0; i < sizeof(aux); i++)
printf(" %02X", aux[i]);
printf("\n");
return 0;
}
推荐阅读
- python - gensim.models.HdpModel实现层次狄利克雷过程时无法获取主题编号
- javascript - history.push() 不能在同一页面上使用 react
- vue.js - 如何在我的 Vue js 应用程序中从 PrimeVue 构建“步骤”组件?
- c++ - 找不到 -lsfml-graphics-d - Code::Blocks 20.03
- python - 如何使用python解析苹果音乐
- python - 如何从 Scrapy 响应中提取值
- django - 'ManyRelatedManager' 对象没有属性 - Django
- localhost - 禁止您无权访问此资源。Apache/2.4.48 (Win64) OpenSSL/1.1.1k PHP/7.4.20 服务器在 localhost 端口 80
- reactjs - 如何修复此错误类型错误:无法在反应 js 中读取未定义的属性(读取“长度”)
- jmeter - 无法从 jmeter 中的先前响应中提取数据