简体   繁体   English

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

[英]Generating a compile-time constant integer from a literal string

I have a problem with non-portable code that works as intended on ARM RealView compiler, but VC++, GCC refuse to compile it and QAC++(a static analysis tool) issues a warning. 我有一个问题,非可移植代码在ARM RealView编译器上按预期工作,但VC ++,GCC拒绝编译它,QAC ++(静态分析工具)发出警告。

The problem 问题

I have a system that needs to parse mnemonic identifiers in messages. 我有一个系统需要解析消息中的助记符标识符。 The mnemonics are all three character 8-bit ASCII strings. 助记符都是三个字符的8位ASCII字符串。 To simplify and optimise parsing rather than performing string compare against the mnemonic string I pack the string into an 32-bit integer and perform an integer comparison. 为了简化和优化解析而不是对助记符字符串执行字符串比较,我将字符串打包成32位整数并执行整数比较。

Further in order to be able to use a switch/case rather than if-elseif chain, I have a macro that takes a literal string and generates the associated integer, which in ARM RealView is a compile time constant, but not in GCC x86/Linux or VC++/Windows: 此外,为了能够使用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])))

This is then used on the ARM target code as follows: 然后将其用于ARM目标代码,如下所示:

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

    case CONST_MNEMONIC(SSD) :
        ...
        break ;

    case CONST_MNEMONIC(DEL) :
        ...
        break ;

    default:
        ...
        break ;
}

The case label of course must be a compile-time constant, but apparently this is not the case for all compilers. 案例标签当然必须是编译时常量,但显然所有编译器都不是这样。 The code is non-portable, and either I guess undefined or implementation defined behaviour, or just plain wrong! 代码是不可移植的,我想是未定义或实现定义的行为,或者只是错误!

The questions 问题

The obvious portable solutions have disadvantages of efficiency and maintainability, so I have two questions: 明显的便携式解决方案存在效率和可维护性的缺点,因此我有两个问题:

  1. Why is this code not portable - what makes the macro not compile-time constant in some compilers? 为什么这段代码不可移植 - 是什么让宏在某些编译器中没有编译时间不变?

  2. Is there a portable solution to generating the desired compile time constant from the mnemonic string? 是否有便携式解决方案从助记符字符串生成所需的编译时间常量?

With C++11 you could use a constexpr function: 使用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]);
}

It compiles fine here with gcc 4.8 and clang 3.4... 这里用gcc 4.8和clang 3.4编译好......

In C++11, you may use: 在C ++ 11中,您可以使用:

constexpr uint32_t CONST_MNEMONIC(const char (&s)[4])
{
    return (uint32_t(s[2]) << 16) | (uint32_t(s[1]) << 8) | uint32_t(s[0]);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM