2016-04-12 89 views
1

我提出的内联函数库与测试平台字节序处理和做转换的最佳风格..在C++中,什么是尾数转换

我第一次尝试构建这样的功能:

inline uint32_t NativeToLittle(uint32_t in) 
{ 
    if(littleEndian()) 
     return in; 
    else 
    { 
     uint32_t var = 0; 
     ((uint16_t*)&var)[0] = NativeToLittle(((uint16_t*)&in)[1]); 
     ((uint16_t*)&var)[1] = NativeToLittle(((uint16_t*)&in)[0]); 

     return var; 
    } 
} 

这个工作在某些平台上,但与激进的优化选项GCC,它失败(铸造uint32_t的*到uint16_t *跑的严格别名规则相抵触。)

鉴于别名规则作出的提工会,我重写了func蒸发散用工会进行转换,这样的:

inline uint32_t swapEndian(uint32_t in) 
{ 
    union ds 
    { 
     uint32_t a; 
     uint16_t b[2]; 
    }; 

    ds var; 
    ds out; 
    var.a = in; 
    out.b[0] = swapEndian(var.b[1]); 
    out.b[1] = swapEndian(var.b[0]); 

    return out.a; 
} 

这个工作对我已经试过了所有平台上,但我并不清楚它是否是好作风。我记得看过一段视频,那位演讲者说这个使用工会进行转换的方案是无效的,因为只有访问工会的一个成员才有效(我不记得这次谈话的网址,对不起)。此外,Stroustrup的JSF编码标准规定“不应使用工会”。

别名规则中唯一的其他相关事物是转换为char类型是有效的。不过,将其转换为字符缓冲区并返回可能非常难看。

那么..这样的结构代码的最佳方式是什么,这是符合标准和合理的可读性?

+3

工会招的确是UB(你可以不读除最后写成的成员之外的成员)。使用位移等。 –

+1

看看Boost Endian是如何做到的。 – GManNickG

回答

0
inline uint32_t swapEndian(uint32_t in) 
{ 
    return (in >> 24) & 0xFF   | //move byte 3 to byte 0 
      (in >> 8) & (0xFF << 8) | //move byte 2 to byte 1 
      (in << 8) & (0xFF << 16) | //move byte 1 to byte 2 
      (in << 24) & (0xFF << 24); | //move byte 0 to byte 1 
} 
+0

这对OP的代码做了不同的转换(不清楚他是否打算这么做) –

+0

嗯,我从来没有听说过以2字节为增量进行字节序排列的平台。如果这真的是OP想要的,那么它简化为(in >> 16)&0xFFFF | (in << 16)&(0xFFFF << 16)' – smead

+0

'0xFFFF'已签名,所以你的意思是(in >> 16)| ((在&0xFFFF)<< 16)' –

1

这很糟糕。你几乎不应该检查处理器的字节顺序。如果进行转换,则应将外部格式的字节数组转换为内部格式,或从内部格式转换为外部格式的字节数组。

您的功能从一开始就有误导性。 “in”参数并不是真正的uint32_t。你应该写如

uint32_t readExternalInt (unsigned char* p) { 
    return (p [aaa] << 24) | (p [bbb] << 16) | (p [ccc] << 8) | p [ddd]; 
} 

适当的值为aaa,bbb,ccc和ddd。看看这是多短?它适用于每个处理器,无论是生物传感器,littleendian,mixedendian,颠倒,站在脑后,或任何其他。

1

虽然我不喜欢微距的,合理的解决方案是从网络代码

例如,使用人htons:

Linux Programmer's Manual 

NAME 
    htonl, htons, ntohl, ntohs - convert values between host and network 
    byte order 

SYNOPSIS 
    #include <arpa/inet.h> 

    uint32_t htonl(uint32_t hostlong); 

    uint16_t htons(uint16_t hostshort); 

    uint32_t ntohl(uint32_t netlong); 

    uint16_t ntohs(uint16_t netshort); 

DESCRIPTION 
    The htonl() function converts the unsigned integer hostlong from host 
    byte order to network byte order. 
.... 
+0

我正在使用这些函数来实现散列函数,所以它对性能非常敏感 - 重要的是它会在不需要的体系结构中消失。所以我认为它或者是高度可优化的内联或者用宏来防止它们的每一次使用。我宁愿去内联路线。 – DuSTman

+0

我也更喜欢内联。也许我应该只建议使用命名风格。这些历史名称在许多应用中都可以找到。我确定我已经看到了这些宏的实现...并且使用-E选项相对容易。在我的Ubuntu 15.10上,我可以查看“/usr/include/netinet/in.h” –