我在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])))
然后在ARM目标代码上使用它,如下所示:
switch( packed_mnemonic )
{
case CONST_MNEMONIC(RST) :
...
break ;
case CONST_MNEMONIC(SSD) :
...
break ;
case CONST_MNEMONIC(DEL) :
...
break ;
default:
...
break ;
}
案例标签当然必须是编译时常量,但显然所有编译器都不是这样。代码是不可移植的,我想是未定义的或实现定义的行为,或者只是简单的错误!
明显的便携式解决方案存在效率和可维护性的缺点,因此我有两个问题:
为什么这段代码不可移植?是什么让宏在某些编译器中的编译时间不变?
是否存在从助记符字符串生成所需编译时常量的可移植解决方案?
答案 0 :(得分: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]);
}
答案 1 :(得分:3)
这里用gcc 4.8和clang 3.4编译好......
在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]);
}