C++ 中的 unsigned int 与 unsigned short 的区别

unsigned int vs unsigned short difference in c++

我有以下内容:

#include <iostream>                                          

using namespace std;                                         

float f1(unsigned int x, unsigned int y)                     
{                                                            
    float val;                                               
    val = float(y-x)/(y+x);                                  
    return val;                                              
}                                                            

float f2(unsigned short x, unsigned short y)                 
{                                                            
    float val;                                               
    val = float(y-x)/(y+x);                                  
    return val;                                              
}                                                            

int main()                                                   
{                                                            
    cout << f1(9612, 9038) << "\n" << f2(9612, 9038) << endl;
    return 0;                                                
}                                                            

在输出中,我从 f1f2 得到两个不同的值,尽管我希望输出相同,因为函数相似。您能解释一下差异的来源吗?

虽然由于两个函数都使用无符号值,人们可能认为减法会导致两个值都为正数,但由于在对数字类型的运算符算术求值之前发生了积分提升,因此人们可能会错了。

cppreference describes arithmetic operator conversions:

If the operand passed to an arithmetic operator is integral or unscoped enumeration type, then before any other action (but after lvalue-to-rvalue conversion, if applicable), the operand undergoes integral promotion. If an operand has array or function type, array-to-pointer and function-to-pointer conversions are applied. ...

整体推广是这种转化发生的地方。关于这个问题,cppreference states the following:

Prvalues of small integral types (such as char) may be converted to prvalues of larger integral types (such as int). In particular, arithmetic operators do not accept types smaller than int as arguments, and integral promotions are automatically applied after lvalue-to-rvalue conversion, if applicable. This conversion always preserves the value.

因此,如果在数学运算中使用小于整数的类型,则会将其转换为整数。这是第二种情况下负值的原因——操作数在减法之前转换为 int,结果产生负值。将该特定表达式视为 ((int)y - (int)x) 可能更容易,这使得它显然可以为负数。

注意 y - x 是负数。它的类型仍然是 unsigned short / int。在这种情况下,您往往会得到 2 的补码而不是负数,这是不同的,因为 sizeof(short) 和 sizeof(int) 对您来说是不同的。

我想你的意思是

float f1(unsigned int x, unsigned int y)                     
{                                                            
    float val;                                               
    val = float( float( y ) - x ) / ( y + x );                                  
    return val;                                              
}  

在表达式中

y-x
由于整数提升,

类型 unsigned short 的对象 xy 被提升为类型 int。你可以想象成

( int )y - ( int ) x

如果 y 小于 x 那么结果将为负数。

xy 的类型为 unsigned int 时,结果的类型也为 unsigned int.

因为y小于xy-x小于0,你用unsigned int和unsigned short,所以'converted'变成positive数字,根据它们的最大范围,是不同的。