C++ 指针投射端点

C++ 指针投射端点,c++,c,compiler-construction,embedded,endianness,C++,C,Compiler Construction,Embedded,Endianness,在我的电脑上编译和运行时,上面的C代码会打印0x1f00 但是,当我将其闪存到嵌入式目标(uController)并进行调试时,我发现 (*X).Element1[0]=0x001f 1-为什么PC和嵌入式目标上的结果不同 2-我可以在该代码中修改什么,以便在PC机箱中打印0x001f, 在不改变代码核心的情况下(通过添加编译器选项或其他可能的方式)。可移植的方法是改变F2的定义: #include "stdio.h" typedef struct CustomStruct { short

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

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

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

2-我可以在该代码中修改什么,以便在PC机箱中打印
0x001f

在不改变代码核心的情况下(通过添加编译器选项或其他可能的方式)。

可移植的方法是改变
F2
的定义:

#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;
}
当您将一个对象重新解释为一个字符数组时,您将公开表示的实现细节,它本质上是不可移植的,并且。。。依赖于实现


如果您需要进行I/O,即使用固定的、指定的外部接线格式进行接口,请使用诸如转换的功能,并将平台细节留给您的库。

可移植的方法是更改
F2
的定义:

#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;
}
当您将一个对象重新解释为一个字符数组时,您将公开表示的实现细节,它本质上是不可移植的,并且。。。依赖于实现


如果您需要进行I/O,即使用固定的、指定的外部接线格式进行接口,请使用诸如转换之类的函数,并将平台细节留给您的库。

似乎PC是小端,目标是大端,或具有16位字符

除非用
short*
引用替换
char*
引用,或者使用宏来抽象微控制器和PC之间的差异,否则没有很好的方法修改PC上的C代码

例如,您可以制作一个宏
PACK_BYTES(hi,lo)
,该宏以相同的方式将两个字节打包为一个短字节,而不考虑机器端号。你的例子变成:

void F2(short * p)
{
    *p = 0x1F;
}

void F1(CustomStruct* X)
{
    F2(&X.Element1[0]);
    printf("s = %x\n", (*X).Element1[0]);
}
#包括“stdio.h”
#定义PACK_字节(hi,lo)((short)((hi)和0xFF))元素1[0]);
printf(“s=%x\n”,(*x).Element1[0]);
}
内部主(空)
{
客户结构;
F1&s;
返回0;
}

似乎PC是小端,目标是大端,或者是16位字符

除非用
short*
引用替换
char*
引用,或者使用宏来抽象微控制器和PC之间的差异,否则没有很好的方法修改PC上的C代码

例如,您可以制作一个宏
PACK_BYTES(hi,lo)
,该宏以相同的方式将两个字节打包为一个短字节,而不考虑机器端号。你的例子变成:

void F2(short * p)
{
    *p = 0x1F;
}

void F1(CustomStruct* X)
{
    F2(&X.Element1[0]);
    printf("s = %x\n", (*X).Element1[0]);
}
#包括“stdio.h”
#定义PACK_字节(hi,lo)((short)((hi)和0xFF))元素1[0]);
printf(“s=%x\n”,(*x).Element1[0]);
}
内部主(空)
{
客户结构;
F1&s;
返回0;
}

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

#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;
}
这将这两个字节中的第一个设置为
0x00
,第二个设置为
0x1f
。问题是C++没有指定第一个或第二个字节对整个代码<>代码<>的值,所以不同的平台可以做不同的事情。特别是,一些平台说,设置第一个字节会影响
short
16位的“最高有效”位,设置第二个字节会影响
short
16位的“最低有效”位。其他平台则相反;设置第一个字节会影响最低有效位,设置第二个字节会影响最高有效位。这两种平台行为分别称为big-endian和little-endian


独立于这些差异而获得一致行为的解决方案是不以这种方式访问
short
的字节。相反,您应该简单地使用该语言定义的方法(例如使用位运算符和算术运算符)操纵
short
的值

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

但请记住,这样的石膏一般是不安全的;您应该只将指针转换回最初转换的位置。

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

#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;
}
这将这两个字节中的第一个设置为
0x00
,第二个设置为
0x1f
。问题是C++没有指定第一个或第二个字节对整个代码<>代码<>的值,所以不同的平台可以做不同的事情。特别是,一些平台说,设置第一个字节会影响
short
16位的“最高有效”位,设置第二个字节会影响
short
16位的“最低有效”位。其他平台则相反;设置第一个字节会影响最低有效位,设置第二个字节会影响最高有效位。这两种平台行为分别称为big-endian和little-endian


独立于这些差异而获得一致行为的解决方案是不以这种方式访问
short
的字节。相反,您应该简单地使用该语言定义的方法(例如使用位运算符和算术运算符)操纵
short
的值

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

但请记住,这样的石膏一般是不安全的;您只需将指针投射回最初的投射源。

非常感谢。问题是,由于许多原因,我只能更改函数F2的主体。我不能改变它的原型。有没有办法在Y被铸造之前找到它的尺寸?非常感谢。问题是,由于许多原因,我只能更改函数F2的主体。我不能改变它的原型。有没有办法在Y被铸造之前找到它的尺寸?非常感谢。问题是,由于许多原因,我只能更改函数F2的主体。我不能改变它的原型。是th吗