【问题标题】:Can the multiplication of two unsigned shorts really lead to undefined behaviour?两个无符号短裤的乘法真的会导致未定义的行为吗?
【发布时间】:2017-04-08 16:59:54
【问题描述】:

我花了一些时间浏览这个网站;特别是这个问题:Is ((a + (b & 255)) & 255) the same as ((a + b) & 255)?

这样做,我得出的结论是

int main()
{
    unsigned short i = std::numeric_limits<unsigned short>::max();
    unsigned short j = i;
    auto y = i * j;
}

由于将ij 类型提升为int,可能导致未定义的行为,随后在乘法时溢出!也许ij 甚至不需要这么大。

我的结论是,例如,在unsigned short 为 16 位且int 为 32 位的系统上,行为可能未定义

我说的对吗?

【问题讨论】:

  • 不,这是定义的行为(witch 变为与(i*j)%std::numeric_limits&lt;unsigned short&gt;::max() 相同的值)而不考虑溢出
  • @apple 不,这是不正确的。
  • 很遗憾您不能对评论投反对票。
  • @Yakk @ FitzwilliamBennet-Darcy 你能解释一下为什么它是未定义的吗?我不认为ij 适合prvalue 作为@krzaq 报价
  • @appleapple 他们将首先进行左值到右值的转换。

标签: c++ language-lawyer


【解决方案1】:

是的,这是可能的,而且您的示例在大多数桌面架构上可能未定义。

为了这个例子,我们假设 int 是 32 位 2 的补码类型,unsigned short 是 16 位。

我使用 N4140 作为报价单。

在乘法之前,两个值都被提升为int

§ 4.5 [conv.prom] / 1

除 bool、char16_t、char32_t 或 wchar_t 其整数转换等级 (4.13) 小于 如果 int 可以表示所有,则 int 可以转换为 int 类型的纯右值 源类型的值;

然后:

§ 5 [expr] / 4

如果在计算表达式期间,结果不是 数学定义或不在可表示值的范围内 它的类型,行为未定义。

由于 65535 * 65535 (4294836225) 的结果未在我们的 32 位 int 中定义(取值范围为 [-2147483648,2147483647]),因此行为未定义。

【讨论】:

  • 它在我的电脑上溢出,上面的例子是用 VS 2013 编译的。
  • 很好的答案!我认为升级规则是 C 语言中最糟糕的事情之一(就语言设计而言),不幸的是被 C++ 采用。它们是无数细微错误的来源。幸运的是,编译器有时会发出警告。
  • 如果值不适合 int,表达式的类型是否会提升为 unsigned int
  • @0x499602D2 不,我引用了相关段落
  • @vsoftco 万一促销改变了价值(这是唯一的问题),您可以使用 -Wconversion,如下所述:gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
猜你喜欢
  • 2020-10-19
  • 1970-01-01
  • 2015-01-16
  • 2016-02-17
  • 1970-01-01
  • 2014-08-11
  • 2016-09-04
  • 1970-01-01
  • 2013-04-24
相关资源
最近更新 更多