2013-07-03 12 views
0

考虑下面的代码:字节序变通所需

#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

向我们展示你如何填充'部件1 ' –

+0

对不起,我没有明白你的意思。你的意思是说你需要F2的实际身体吗?我认为它没用,因为我保证在F2的末尾你有Y [0] = 0x00和Y [1] = 0x1F。 –

+0

您正试图提供该保证。我们试图告诉你如何,但除非你给我们提供真正的代码来工作,否则我们只能猜测你在做什么。 –

回答

2

如果F2()正在接收char *,那么它必须做一些非常奇怪的事情,以便引起与endian相关的问题。

这些只发生在一次访问更多比一个char,除非它是手动进行这种访问时被破坏。它是否把它的论点回到short *之类的东西?

总之,显示更多代码。

+0

我已经添加了问题的编译代码:) 如果您尝试过,它将打印0x1f00。 但是,当此代码闪烁到嵌入式目标和调试(uController)(* X).Element1 [0] = 0x001f。 –

6

Endianness不是一个编译器问题,甚至不是操作系统问题,而是一个平台问题。没有编译器选项或“替代方案”的字节顺序。然而,有转换例程,以便您可以规范存储数据的字节顺序。

ntoh例程documented here将重新排列从网络顺序(big endian)指向主机顺序(无论是大还是小,取决于主机类型)的字节数。从主机订单到网络订单,也有相反的方向功能hton

如果要规格化存储在数据结构中的字节,则需要在存储数据或尝试读取数据时自行完成。

下面是函数模板,我写了ntohxhtonx正在对数据存储的类型一概而论,无论是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)); 
}; 
+0

当然,ntoh/hton只能保证一个表示将在Big Endian中,并且一个表示可以被您的机器使用而不管字节顺序如何;它没有提供直接的机制来保证Little Endian中的一个表示。 – Medinoc

+0

@Medinoc:对,这是真的。 –