C++通常的算术转换不转换
C++ usual arithmetic conversions not converting
首先,我想指出的是,我确实阅读了一些标题大致相似的其他答案。然而,这些要么是指我认为是旧版本的标准,要么是指促销,而不是转换。
我一直在";C++速成课程";,作者在探索内置运算符的一章中陈述了以下内容:
如果没有任何浮点提升规则适用,则检查是否有任何一个参数签名。如果是,则两个操作数都变为有符号。最后,与浮点类型的提升规则一样最大的操作数用于提升另一个操作数:。。。
如果我正确阅读了标准,这不是真的,因为根据cppreference.com,
如果两个操作数都有符号或都无符号,则转换秩较小的操作数将转换为整数转换秩较大的操作数
否则,如果无符号操作数的转换秩大于或等于有符号操作数转换秩,则有符号操作数会转换为无符号操作数数的类型。
否则,如果有符号操作数的类型可以表示无符号操作数中的所有值,则无符号操作数会转换为有符号操作数数的类型
否则,两个操作数都将转换为有符号操作数类型的无符号对应对象。
更让我困惑的是以下代码:
printf("Size of int is %d bytesn", sizeof(int));
printf("Size of short is %d bytesn", sizeof(short));
printf("Size of long is %d bytesn", sizeof(long));
printf("Size of long long is %d bytesn", sizeof(long long));
unsigned int x = 4000000000;
signed int y = -1;
signed long z = x + y;
printf("x + y = %ldn", z);
产生以下输出:
Size of int is 4 bytes
Size of short is 2 bytes
Size of long is 8 bytes
Size of long long is 8 bytes
x + y = 3999999999
根据我对标准的理解,y
本应转换为unsigned int
,从而导致错误的结果。结果是正确的,这使我假设在这种情况下不会发生转换。为什么?如果能就此事提出申诉,我将不胜感激。非常感谢。
(我也很感激有人告诉我,我在现实生活中永远不需要这种神秘的知识,即使这不是真的——只是为了让我安心。)
将负有符号值转换为无符号值会产生与其对应的二进制补码值。添加此无符号值将导致溢出,然后产生与添加负值完全相同的值。
顺便说一句:这就是处理器做减法的诀窍(或者我在现代错了吗?)。
如果我正确阅读了标准,这不是真正的
你是对的。CCC是错误的。
根据我的理解,y应该转换为无符号int,
确实如此。
结果是正确的,这让我假设在这种情况下不会发生转换。
你认为错了。
由于-1不是可表示的无符号数,它只是简单地转换为可表示的数,是可表示的,并且与-1一致,以可表示值的数量为模。当你把它加到x上时,结果比任何可表示的值都大,所以结果是与模一致的可表示值。由于模运算的神奇之处,你可以得到正确的结果。
您添加了一个无符号int和一个有符号int,因此两个操作数的转换秩相同。因此,第二条规则将适用(强调我的):
[否则,]如果无符号操作数的转换秩大于或等于有符号操作数转换秩,则有符号操作数会转换为无符号操作数类型。
- -1被转换为无符号类型,方法是向其添加比最高无符号int大2的最小幂(事实上,它以2的补码表示)
- 这个数字加上400000000,结果是总和和2的幂的模(实际上丢弃了它的高位)
- 而你只是得到了预期的结果
标准强制转换为无符号类型,因为无符号溢出是由标准定义的,而无符号溢出不是。
我也很感激有人告诉我我永远都不需要这个现实生活中的神秘知识
上面没有提到一个隐含的推广,这是错误的常见原因:
unsigned short x = 0xffff;
unsigned short y = 0x0001;
if ((x + y) == 0)
这样做的结果是错误的,因为算术运算被隐式提升到至少int。
从代码片段的第一个print语句的输出中可以明显看出,由于int的大小是4个字节,因此无符号int值的范围可以从0到4294967295。(2^32-1)
因此,以下声明完全有效:
unsigned int x = 4000000000;
请记住,将x声明为无符号整数会使其自身的(+ve)范围是有符号对应项的两倍,但它位于完全相同的范围内,因此它们之间的转换是可能的。
signed int y = -1;
signed long z = x + y;
printf("x + y = %ldn", z);
因此,对于上面代码的其余部分,y和z的操作数是有符号(+ve/-ve)还是无符号(+ve)在这里无关紧要,因为您首先要处理的是一个无符号整数,通过在有符号版本中添加UINTMAX+1
,将有符号整数转换为相应的无符号整数版本。这里UINTMAX
代表最大的无符号值,它与最小的2次方相加(2^0=1)。最终结果显然会大于我们可以存储的值,因此它被视为模来收集正确的无符号整数。
但是,如果您要将x转换为已签名:
signed int x = 4000000000;
int y = -1;
long z = x + y;
printf("x + y = %ldn", z);
你会得到你可能期望的:
x + y = -294967297
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 正在将指针转换为范围
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 是否可以从int转换为enum类类型
- 了解 GLM- openGL 中的相机转换
- 将无符号char*转换为std::istream*C++