从文字字符串生成编译时常量整数

Cli*_*ord 6 c++ embedded portability realview

我有一个问题,非可移植代码在ARM RealView编译器上按预期工作,但VC++,GCC拒绝编译它,QAC++(静态分析工具)发出警告.

问题

我有一个系统需要解析消息中的助记符标识符.助记符都是三个字符的8位ASCII字符串.为了简化和优化解析而不是对助记符字符串执行字符串比较,我将字符串打包成32位整数并执行整数比较.

此外,为了能够使用switch/case而不是if-elseif链,我有一个宏,它接受一个文字字符串并生成相关的整数,在ARM RealView中是一个编译时常量,但不是在GCC x86/Linux或VC++/Windows:

// Note:  Do not change C cast to static_cast because compiler complains when used in switch/case
#define CONST_MNEMONIC( mn ) ((uint32_t)(((#mn)[2]<<16)|((#mn)[1]<<8)|((#mn)[0])))
Run Code Online (Sandbox Code Playgroud)

然后将其用于ARM目标代码,如下所示:

switch( packed_mnemonic )
{
    case CONST_MNEMONIC(RST) :
        ...
        break ;

    case CONST_MNEMONIC(SSD) :
        ...
        break ;

    case CONST_MNEMONIC(DEL) :
        ...
        break ;

    default:
        ...
        break ;
}
Run Code Online (Sandbox Code Playgroud)

案例标签当然必须是编译时常量,但显然所有编译器都不是这样.代码是不可移植的,我想是未定义或实现定义的行为,或者只是错误!

问题

明显的便携式解决方案存在效率和可维护性的缺点,因此我有两个问题:

  1. 为什么这段代码不可移植 - 是什么让宏在某些编译器中的编译时间不变?

  2. 是否有便携式解决方案从助记符字符串生成所需的编译时间常量?

Som*_*ude 5

使用C++ 11,您可以使用一个constexpr函数:

constexpr int CONST_MNEMONIC(const char* s)
{
    return (static_cast<int>(s[2]) << 16) +
           (static_cast<int>(s[1]) <<  8) +
            static_cast<int>(s[0]);
}
Run Code Online (Sandbox Code Playgroud)

  • 在C++ 11中比在C++ 03中容易得多.我挣扎了好几天来制造一些让你感觉像是30秒的东西.好的,是的 也许我有点嫉妒. (4认同)