指针铸造Endianness

时间:2013-07-03 22:42:59

标签: c++ c compiler-construction embedded 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 = %x\n", (*X).Element1[0]);
}

int main(void)
{
  CustomStruct s;
  F1(&s);

  return 0;
}

上面的C代码在编译并在我的电脑上运行时打印0x1f00

但是当我将它闪存到嵌入式目标(uController)并进行调试时,我发现了 (*X).Element1[0] = 0x001f

1-为什么PC和嵌入式目标上的结果有所不同?

2-我可以在此代码中修改哪些内容,以便在PC机箱中打印0x001f, 不改变代码核心(通过添加编译器选项或其他东西)。

3 个答案:

答案 0 :(得分:3)

short通常是两个字节和16位。当你说:

short s;
((char*)&s)[0] = 0x00;
((char*)&s)[1] = 0x1f;

这将这两个字节中的第一个设置为0x00,将这两个字节中的第二个设置为0x1f。问题是C ++没有指定第一个或第二个字节对整个short的值的设置,因此不同的平台可以做不同的事情。特别是,有些平台认为设置第一个字节会影响short 16位的“最高有效”位,而设置第二个字节会影响short的'最低有效'位。 16位。其他平台则相反;设置第一个字节会影响最低有效位,设置第二个字节会影响最高有效位。这两种平台行为分别称为big-endian和little-endian。


获得与这些差异无关的一致行为的解决方案是不以这种方式访问​​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;
}

但请记住,这样的演员阵容一般不安全;你应该只将指针强制转换回最初投射的内容。

答案 1 :(得分: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 and ntohs之类的函数进行转换,并将平台细节保留在库中。

答案 2 :(得分:1)

看起来PC是小端,目标是big-endian,或者是16位char。

在PC上修改C代码没有很好的方法,除非用char *引用替换short *引用,并且可能使用宏来抽象微控制器和你的微控制器之间的差异PC。

例如,您可以创建一个宏PACK_BYTES(hi, lo),它以相同的方式将两个字节打包成一个short,而不管机器端序。你的例子变成了:

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