指针转换字节序

问题描述 投票:0回答:3
#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 = %x\n", (*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
, 无需更改代码核心(通过添加编译器选项或其他内容)。

c++ c embedded endianness
3个回答
3
投票

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; }

但请记住,这种类型转换通常并不安全;你应该只将指针投射回原来的位置。


2
投票
可移植的方式是改变

F2

的定义:

void F2(short * p) { *p = 0x1F; } void F1(CustomStruct* X) { F2(&X.Element1[0]); printf("s = %x\n", (*X).Element1[0]); }

当您将对象重新解释为字符数组时,您暴露了表示的

实现细节,这本质上是不可移植的并且......依赖于实现。

如果您需要进行 I/O,即与固定的、指定的外部线路格式的接口,请使用

htons

ntohs
 等函数进行转换并将平台细节留给您的库。


1
投票
PC 似乎是小端字节序,而目标要么是大端字节序,要么具有 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 = %x\n", (*X).Element1[0]); } int main(void) { CustomStruct s; F1(&s); return 0; }
    
© www.soinside.com 2019 - 2024. All rights reserved.