乘以unsigned short会导致未定义的行为吗?

时间:2015-11-16 09:53:46

标签: c++ c++11 types casting integer-promotion

作为" https://stackoverflow.com/questions/33732041/why-static-castunsigned-intushrt-maxushrt-max-yields-correct-value"

的后续行动

我问自己,如果推广所有类型(除了一些例外),其等级低于intint以执行算术运算,在某些情况下可能会导致UB。

e.g:

unsigned short a = 0xFFFF;
unsigned short b = a*a;

由于无符号短语被提升为int进行算术运算,因此会导致:

unsigned short a = 0xFFFF;
unsigned short b = (int)a*(int)a;

由于(int)0xFFFF*(int)0xFFFF导致溢出,并且签名类型的溢出为UB:x,y 的情况下,可以将两个无符号短路x*y > INT_MAX相乘会导致未定义的行为

更新

该问题专门针对int为32位且short为16位的情况。

2 个答案:

答案 0 :(得分:7)

C ++11§3.9.1/ 4,完整报价:
  

无符号整数,声明为unsigned,应遵守算术模2 n 的定律,其中 n < / em>是数字   特定大小整数的值表示中的位数。

除了关于“声明unsigned”的略微误导的措辞之外,这似乎适用于每个仅涉及某些给定无符号类型的参数的算术表达式将产生模2 n的结果 表示该类型。

但是,对于低于int的低转换级别的无符号类型,根本没有算术表达式:明显这样的表达式中的所有参数都至少转换为(1) {1}},或者取决于C ++实现的编号范围,最多int

因此,unsigned int其中a*bab值,(2)可能具有正式的未定义行为。因为它不是unsigned short表达式。它(实际上)是unsigned short表达式。

也就是说,使用一个合理的编译器,它不会引入特殊的大小写,它会注意到正式的UB,并且实际上是8位字节和int最大值,可由unsigned short表示,并且常见的二进制补码有符号整数表示,当转换回int时,结果将,好像它是unsigned short范围内的模运算。这是因为在机器代码级别,两个补码只是模数运算,范围以0为中心。

(1)在实践中,通常会使用每字节8位的实现,其中unsigned short的最大值非常适合unsigned short范围,所以在实践中我们我说的是转换为int (2)例如,对于16位int和32位unsigned short,(2 16 -1) 2 = 2 32 -2×2 16 +1&gt; 2 31 -1,其中最后一个值是最大正int值。 功能

答案 1 :(得分:3)

当您乘以$index = 0; @foreach($tasks as $task) <div class="col-md-9"> <input id="taskfield" name="dynamic[$index]" value="{{ $task->name }}" class="form-control field" type="text"> </div> <div class="col-md-3"> <div class="slideOne"> <input type="checkbox" value="1" id="slideOne" name="check[$index]" @if($task->finished == 1) checked @endif/> <label for="slideOne"></label> </div> </div> $index++; @endforeach 时,会有一个implicit conversion,并且该值会在C ++ 11中转换为unsigned short * unsigned shortdocumentation说:

  

小积分类型(例如char)的Prvalues可以转换为   较大整数类型的prvalues(例如int)。特别是,   算术运算符不接受小于int 的类型作为参数

因此会导致未定义的行为。