是否乘以无符号短因子未定义行为? [英] Does multiplying unsigned short cause undefined behaviour?

查看:258
本文介绍了是否乘以无符号短因子未定义行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为为什么static_cast< unsigned int>(USHRT_MAX * USHRT_MAX)产生正确的值?



我问自己如果促销所有类型code> int 到 int 执行算术运算可能会导致UB。



例如:

 无符号短a = 0xFFFF; 
unsigned short b = a * a;

无符号short被提升为 int 算术运算将导致:

 无符号短a = 0xFFFF; 
unsigned short b =(int)a *(int)a;

As (int)0xFFFF *(int)0xFFFF 导致溢出,并且有符号类型的溢出是UB: x,y > x * y> INT_MAX

更新





>

这个问题专门针对 int 是32位和 short 是16位。

解决方案

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


已声明为 unsigned 的无符号整数应符合算术模2的规则 n 其中 是整数的特定大小的值表示中的位的数字


除了有关 unsigned 的略有误导的措辞这似乎适用于每个只涉及某个给定无符号类型的参数的算术表达式将产生模2 n 的结果。



但是,对于没有符号的低于 int 的转换级别,没有算术表达式:明显这种表达式中的所有参数都被转换最多为(1)至少 int ,或者取决于C ++实现的数字范围,最多为 unsigned int



因此, a * b 其中 a b 无符号short 值,(2)可以有正式未定义的行为。因为它不是无符号short 表达式。这是(在实践中)一个 int 表达式。



在其中注意正式UB,并且在实践中的8位字节和无符号短最大值,可由 int 和普通二进制补码有符号整数表示,结果,当转换回 unsigned short 时,将会像是模运算范围 unsigned short 。这是因为在机器代码级别上的二进制补码只是以0为中心的范围的模运算。







(1)在实践中,通常使用一个8位每字节实现,其中 unsigned short 非常适合 int 范围内,因此在实践中我们讨论的转换最多为 int

(2)例如,对于16位无符号短和32位 int ,(2 16 -1) 2 = 2 32 -2×2 < 2 31 -1,其中最后一个值是最大正< int 值。


As a follow-up to "Why static_cast<unsigned int>(USHRT_MAX*USHRT_MAX) yields correct value?"

I was asking myself if promoting all types (except some exceptions) with a lower rank than int to int to perform arithmetic operations might cause UB in some cases.

e.g.:

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

As unsigned short is promoted to int for arithmetic operations this would result in:

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

As (int)0xFFFF*(int)0xFFFF causes an overflow, and overflow of signed types is UB: Can multiplying two unsigned shorts x,y cause undefined behaviour in the case that x*y > INT_MAX


UPDATE:

The question specifically aims at the case that int is 32-bit and short is 16-bit.

解决方案

C++11 §3.9.1/4, full quote:

Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer.

Apart from the slightly misleading wording about “declared unsigned” this might seem to apply that every arithmetic expression that involve only argument of some given unsigned type, will yield a result modulo 2n for that type.

However, there are no arithmetic expressions at all for unsigned types of lower conversion rank than int: all arguments in an apparent such expression are converted up to (1)at least int, or depending on the number ranges of the C++ implementation, up to unsigned int.

As a result, a*b where a and b are unsigned short values, (2)can have formally Undefined Behavior. Because it's not an unsigned short expression. It's (in practice) an int expression.

That said, with a reasonable compiler that doesn't introduce special casing where it notices formal UB, and with in-practice 8 bit bytes and unsigned short max value that is representable by int, and common two's complement signed integer representation, the result, when converted back down to unsigned short, will be as if it was modular arithmetic in the range of unsigned short. That's because two's complement, at the machine code level, is just modular arithmetic with a range centered on 0.


(1) In practice one will usually be using an 8 bits-per-byte implementation where the maximum value of unsigned short fits well within the int range, so in practice we're talking about a conversion up to int.
(2) E.g., for 16-bit unsigned short and 32-bit int, (216−1)2 = 232−2×216+1 > 231−1, where the last value is the maximum positive int value.

这篇关于是否乘以无符号短因子未定义行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆