作为" https://stackoverflow.com/questions/33732041/why-static-castunsigned-intushrt-maxushrt-max-yields-correct-value"
的后续行动我问自己,如果推广所有类型(除了一些例外),其等级低于int
到int
以执行算术运算,在某些情况下可能会导致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位的情况。
答案 0 :(得分:7)
“无符号整数,声明为
unsigned
,应遵守算术模2 n 的定律,其中 n < / em>是数字 特定大小整数的值表示中的位数。
除了关于“声明unsigned
”的略微误导的措辞之外,这似乎适用于每个仅涉及某些给定无符号类型的参数的算术表达式将产生模2 n的结果 表示该类型。
但是,对于低于int
的低转换级别的无符号类型,根本没有算术表达式:明显这样的表达式中的所有参数都至少转换为(1) {1}},或者取决于C ++实现的编号范围,最多int
。
因此,unsigned int
其中a*b
和a
为b
值,(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 short
。 documentation说:
小积分类型(例如char)的Prvalues可以转换为 较大整数类型的prvalues(例如int)。特别是, 算术运算符不接受小于int 的类型作为参数
因此会导致未定义的行为。