【问题标题】:Initializing a const variable with ntohl()使用 ntohl() 初始化 const 变量
【发布时间】:2014-02-13 23:22:48
【问题描述】:

我正在尝试使用经过适当字节交换的值来初始化全局范围的 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)”或类似的东西,在编译时无法评估。无赖。

我能做些什么来达到同样的目的吗?我需要为适当的结束性初始化值,并且我希望它是一个全局范围的常量。除了滚动我自己的类似 ntohl 的宏之外,有什么方法可以说服 gcc 这样做吗?

(顺便说一句,我注意到 clang 定义了 ntohl() 以便可以在编译时对其进行评估。上面的代码示例与 clang 完美配合。不幸的是,我没有选择编译器。)

【问题讨论】:

    标签: c htonl


    【解决方案1】:

    标准的第 6.7.8/4 节写道

    具有静态存储持续时间的对象的初始化程序中的所有表达式都应为常量表达式或字符串字面量。

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

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

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

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

    #define POTRZEBIE ntohl(0x11223344)
    
    void bar(void)
    {
      const unit32_t a = POTRZEBIE;
      /* ... */
    }
    

    在具有自动存储的变量上,const 限定符表示单次赋值,所以上面的用法没有问题。

    【讨论】:

      【解决方案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
      

      【讨论】:

        猜你喜欢
        • 2017-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-02
        • 1970-01-01
        • 2017-09-21
        • 2014-09-08
        相关资源
        最近更新 更多