指针投射字节序
Pointers Casting Endianness
#include "stdio.h"
typedef struct CustomStruct
{
short Element1[10];
}CustomStruct;
void F2(char* Y)
{
*Y=0x00;
Y++;
*Y=0x1F;
}
void F1(CustomStruct* X)
{
F2((char *)X);
printf("s = %xn", (*X).Element1[0]);
}
int main(void)
{
CustomStruct s;
F1(&s);
return 0;
}
上面的 C 代码在我的 PC 上编译和运行时打印0x1f00
。
但是当我将其闪存到嵌入式目标(uController(并进行调试时,我发现 (*X).Element1[0] = 0x001f
.
1- 为什么PC和嵌入式目标上的结果不同?
2-我可以在此代码中修改什么,以便它在PC机箱中打印0x001f
,无需更改代码核心(通过添加编译器选项或其他内容(。
short
通常是两个字节和16位。当你说:
short s;
((char*)&s)[0] = 0x00;
((char*)&s)[1] = 0x1f;
这会将这两个字节中的第一个设置为 0x00
,将这两个字节中的第二个设置为 0x1f
。问题是C++没有指定第一个或第二个字节对整体short
值所做的设置,因此不同的平台可以做不同的事情。特别是,一些平台说设置第一个字节会影响short
16位中的"最重要"位,而设置第二个字节会影响short
16位中的"最不重要"位。其他平台则相反;设置第一个字节会影响最低有效位,设置第二个字节会影响最高有效位。这两种平台行为分别称为大端和小端。
获得独立于这些差异的一致行为的解决方案是不以这种方式访问short
的字节。相反,您应该简单地使用语言定义的方法(例如按位运算符和算术运算符(操作short
的值。
short s;
s = (0x1f << 8) | (0x00 << 0); // set the most significant bits to 0x1f and the least significant bits to 0x00.
问题是,由于许多原因,我只能更改函数 F2 的主体。我无法更改其原型。有没有办法在 Y 被城堡化之前找到它的大小或其他东西?
不能仅使用 char*
确定原始类型和大小。您必须通过其他方式知道正确的类型和大小。如果除使用 CustomStruct 外从未调用F2
,则只需将char*
转换回CustomStruct
,如下所示:
void F2(char* Y)
{
CustomStruct *X = (CustomStruct*)Y;
X->Element[0] = 0x1F00;
}
但请记住,这样的强制转换通常并不安全;您只应该将指针投射回它最初被强制转换的内容。
可移植的方法是更改F2
的定义:
void F2(short * p)
{
*p = 0x1F;
}
void F1(CustomStruct* X)
{
F2(&X.Element1[0]);
printf("s = %xn", (*X).Element1[0]);
}
当您将对象重新解释为字符数组时,您将公开表示的实现细节,这本质上是不可移植的,并且依赖于实现。
如果您需要执行 I/O,即使用固定的、指定的外部线路格式进行接口,请使用 htons
和 ntohs
等功能进行转换,并将平台细节留给您的库。
是小端序,目标要么是大端序,要么是16位字符。
没有一种方法可以修改PC上的C代码,除非您将char *
引用替换为short *
引用,并且可能使用宏来抽象微控制器和PC之间的差异。
例如,您可以创建一个宏PACK_BYTES(hi, lo)
,以相同的方式将两个字节打包成一个短字节,而不考虑计算机字节序。 您的示例变为:
#include "stdio.h"
#define PACK_BYTES(hi,lo) (((short)((hi) & 0xFF)) << 8 | (0xFF & (lo)))
typedef struct CustomStruct
{
short Element1[10];
}CustomStruct;
void F2(short* Y)
{
*Y = PACK_BYTES(0x00, 0x1F);
}
void F1(CustomStruct* X)
{
F2(&(X->Element1[0]));
printf("s = %xn", (*X).Element1[0]);
}
int main(void)
{
CustomStruct s;
F1(&s);
return 0;
}
- 将字节数组转换为带有字节序问题的指针
- 向指针地址添加 20 个字节偏移量
- 将(N 个字节)无符号字符指针转换为浮点数和双 C++
- 通过浮点指针操作字节向量
- 复制后删除原始数组指针将前 3 个字节设置为 0
- 将uint64_t转换为字节时从不同大小的整数强制转换为指针
- C++向指针地址添加 4 个字节
- 将constexpr字节数组与缓冲区的一部分(指向数据的指针)进行比较
- 从字节指针读取位的差异
- 读取字节后丢失指针
- C++如何从文件中读取十六进制字节并将其存储为指针
- 以C++(Arduino)为单位比较指针到字节
- 2 个指针,0 字节相差但不相等
- Valgrind:将一个指针分配给另一个指针后丢失字节
- ::运算符 delete(指针) 返回释放的字节大小
- _declSpec(Align(16))不将指针与16个字节对齐
- i2c中的字节指针数组
- 如何在 JNA 中获取字节数组作为从 C 字节指针返回的返回
- reinterpret_cast<字符*>(p)或static_cast<字符*>((void*)p))表示字节指针差,哪个更好?
- c++到c#:有3个元素的字节指针数组等于什么?