【发布时间】:2014-03-12 06:51:40
【问题描述】:
以下代码在 C++11 中是否合法?
int16_t x {0xaabb};
int64_t xxxx {0xaaaabbbbccccdddd};
代码来自“The C++ Programming Language”第 4 版(第 150 页)。
众所周知,列表初始化是不允许窄化转换的,在标准对窄化转换的定义中,我们有:
缩小转换是一种隐式转换
— [...]
— 从整数类型或无作用域枚举类型到不能表示原始类型的所有值的整数类型,除非源是常量表达式并且转换后的实际值将适合目标类型并生成原始值当转换回原始类型时。
对照示例代码检查缩小转换规则,我证明示例代码是非法的,因为0xaabb 和0xaaaabbbbccccdddd 不能分别在int16_t 和int64_t 中表示。对吗?
但我不太明白“除非源是常量表达式并且转换后的实际值适合目标类型并且在转换回时会产生原始值原始类型”。我想知道在什么情况下转换后的实际值不能适合目标类型。由于整数类型之间的转换始终有效(尽管在目标类型已签名且源值无法在目标类型中表示的情况下实现定义,但无论如何它不是未定义的行为),“值 转换后是否适合目标类型”?从这个角度来看,我开始质疑我对示例代码正在缩小转换的判断。如果是这样的话,为什么标准总是在条件中放置一些东西?为什么不直接说“除非源是常量表达式,并且转换后的实际值在转换回原始类型时会产生原始值”?
有人可以帮我澄清一下吗?谢谢!
【问题讨论】:
-
我认为问题在于
0xaabb可以被认为是一个“正”常量,但是当分配给int16_t时,它变成了一个负数。嗯,我刚刚回复了一个不再在这里的评论,但我会留下这个,因为它可能会澄清问题。 -
您能否改进标题,以便在问题列表中将此问题与其他问题区分开来?
-
根据经验,它应该是合法的,因为 GCC 会发出警告(因此编译器明显意识到了这个问题),但它不会发出错误。如果它确实是非法的,编译应该会因错误(而不是警告)而中断。
-
@Damon:你的结论不符合。该标准不要求编译器在遇到非法代码时停止编译。所需要的只是诊断出错误,并发出警告。 GCC 上
-pedantic-errors的目的是将此类警告提升为错误。 -
@Damon 标准中没有这样的要求,GCC(就像其他编译器一样)在设计上接受了一些在标准 C++ 中无效的东西,只有一个警告。
标签: c++ c++11 language-lawyer