2014-02-13 96 views
4

我试图初始化一个全局作用域的const变量,它的值正确地进行了字节交换。用ntohl()初始化一个const变量

#include <stdio.h> 
#include <stdint.h> 
#include <arpa/inet.h> 

const uint32_t a = ntohl(0x11223344); 

int main(int argc, char const *argv[]) 
{ 
    printf("%08x\n", a); 
    return 0; 
} 

使用gcc失败,错误:初始化器元素不是常量。是的,好吧,所以gcc头文件将ntohl()定义为一个函数,或者定义为“do {...} while(0)”或类似的东西,这些东西在编译时无法评估。游民。

有什么我可以做到的,它会达到同样的目的吗?我需要初始化适当的结束值,我希望它是一个全局范围的const。有没有什么办法可以说服gcc做到这一点,短短的滚动我自己的类似宏的宏?

(顺便说一句,我注意到,有铿锵再用ntohl()定义,使得它可以在编译时进行评估。上面的代码示例工程完全铿锵。不幸的是我没有得到我的编译器的选择。)

回答

2

初始化它在main()或使用类似(假设的Linux):

#include <endian.h> 
#if __BYTE_ORDER == __LITTLE_ENDIAN 
const uint32_t a = 0x44332211; 
#else 
const uint32_t a = 0x11223344; 
#endif 

或也许

#include <endian.h> 
#define A_ADDR 0x11223344 
#if __BYTE_ORDER == __LITTLE_ENDIAN 
const uint32_t a = __bswap_constant_32(A_ADDR); 
#else 
const uint32_t a = A_ADDR; 
#endif 
3

节6.7.8 /标准的4读取

All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals.

ntohl的调用既不是常量表达式,也不是字符串文字。你不能从这里到达那里。

但无论如何全局变量是坏的,我怀疑这可能是一个不成熟的优化。简单的解决方法是直接在您的代码中使用表达式,这在大端平台上完全没有影响,例如

void foo(void) 
{ 
    const unit32_t a = ntohl(0x11223344); 
    /* ... */ 
} 

更好的是,使用预处理器宏,如在

#define POTRZEBIE ntohl(0x11223344) 

void bar(void) 
{ 
    const unit32_t a = POTRZEBIE; 
    /* ... */ 
} 

在具有自动存储的变量,所述const限定符意味着单个分配,所以与上述的使用没有问题。