C++ 指针投射端点
在我的电脑上编译和运行时,上面的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
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吗