考虑以下代码:
#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;
}
在运行时,在调用函数F1
结束时,我使用不同的编译器得到不同的结果。
(*X).Element1[0] = 0x1f00
和另一个编译器中的(*X).Element1[0] = 0x001f
。
我很清楚这是一个字节序问题。
是否有任何编译器选项或解决方法可供使用,以便无论使用何种编译器都可获得(*X).Element1[0] = 0x001f
?
答案 0 :(得分:6)
Endianness不是编译器问题,甚至也不是操作系统问题,而是平台问题。字节序没有编译器选项或“变通方法”。但是有转换例程,以便您可以规范化存储数据的字节顺序。
ntoh
例程documented here会将从网络顺序(大端)指向的字节重新排序到主机顺序(大或小,取决于主机的类型)。还有hton
个函数朝着相反的方向发展,从主机订单到网络订单。
如果要标准化存储在数据结构中的字节,则需要在存储数据时或在尝试读取数据时自己执行此操作。
以下是我为ntohx
和htonx
编写的函数模板,它们是关于数据存储类型的概括,无论是2字节,4字节还是8字节类型:
template<class Val> inline Val ntohx(const Val& in)
{
char out[sizeof(in)] = {0};
for( size_t i = 0; i < sizeof(Val); ++i )
out[i] = ((char*)&in)[sizeof(Val)-i-1];
return *(reinterpret_cast<Val*>(out));
}
template<> inline unsigned char ntohx<unsigned char>(const unsigned char & v )
{
return v;
}
template<> inline uint16_t ntohx<uint16_t>(const uint16_t & v)
{
return ntohs(v);
}
template<> inline uint32_t ntohx<uint32_t>(const uint32_t & v)
{
return ntohl(v);
}
template<> inline uint64_t ntohx<uint64_t>(const uint64_t & v)
{
uint32_t ret [] =
{
ntohl(((const uint32_t*)&v)[1]),
ntohl(((const uint32_t*)&v)[0])
};
return *((uint64_t*)&ret[0]);
}
template<> inline float ntohx<float>(const float& v)
{
uint32_t const* cast = reinterpret_cast<uint32_t const*>(&v);
uint32_t ret = ntohx(*cast);
return *(reinterpret_cast<float*>(&ret));
};
template<class Val> inline Val htonx(const Val& in)
{
char out[sizeof(in)] = {0};
for( size_t i = 0; i < sizeof(Val); ++i )
out[i] = ((char*)&in)[sizeof(Val)-i-1];
return *(reinterpret_cast<Val*>(out));
}
template<> inline unsigned char htonx<unsigned char>(const unsigned char & v )
{
return v;
}
template<> inline uint16_t htonx<uint16_t>(const uint16_t & v)
{
return htons(v);
}
template<> inline uint32_t htonx<uint32_t>(const uint32_t & v)
{
return htonl(v);
}
template<> inline uint64_t htonx<uint64_t>(const uint64_t & v)
{
uint32_t ret [] =
{
htonl(((const uint32_t*)&v)[1]),
htonl(((const uint32_t*)&v)[0])
};
return *((uint64_t*)&ret[0]);
}
template<> inline float htonx<float>(const float& v)
{
uint32_t const* cast = reinterpret_cast<uint32_t const*>(&v);
uint32_t ret = htonx(*cast);
return *(reinterpret_cast<float*>(&ret));
};
答案 1 :(得分:2)
如果F2()
收到char *
,那么它必须做一些非常奇怪的事情才能引起与字谜相关的问题。
这些只在一次访问 more 而不是一个char
时发生,除非它在被破坏时手动进行此类访问。是将它的论证转回short *
还是其他什么?
简而言之,显示更多代码。