C++ 有符号字符的乘法问题
在讨论答案时,我发现下面的代码在visual studio中打印C++ 有符号字符的乘法问题,c++,visual-studio,C++,Visual Studio,在讨论答案时,我发现下面的代码在visual studio中打印-1和1。为什么?在我看来,它应该打印两个1s,而不是乘法过程中的溢出 signed char c1 = numeric_limits<signed char>::min(); signed char c2 = -1; cout << c1 * c2 / c1 << endl; signed char result = c1 * c2; cout << result / c1 <
-1
和1
。为什么?在我看来,它应该打印两个1
s,而不是乘法过程中的溢出
signed char c1 = numeric_limits<signed char>::min();
signed char c2 = -1;
cout << c1 * c2 / c1 << endl;
signed char result = c1 * c2;
cout << result / c1 << endl;
signed char c1=numeric_limits::min();
有符号字符c2=-1;
cout整数溢出被认为是UB。这意味着编译器将考虑<代码>(C1*C2/C1)完全等同于<代码> C2< /代码>。
您可以查看其他信息。整数溢出被视为UB。这意味着编译器将考虑<代码>(C1*C2/C1)完全等同于<代码> C2< /代码>。
您可以查看其他信息。c1
的值可能类似于-128
。在乘法中,整数提升将导致c1
和c2
在执行运算之前转换为类型int
c1*c2
然后将是一个值为128
的int
,因此c1*c2/c1
将是一个值为-1
的int
-1
对于第一个输出,我认为是正确的
对于第二个版本,通常情况下,c1*c2
的结果赋值将不适合有符号字符
,并将转换为实现定义的结果,例如,可能-128
而不是128c1
可能具有类似-128
的值。在乘法中,整数提升将导致c1
和c2
在执行运算之前转换为类型int
c1*c2
然后将是一个值为128
的int
,因此c1*c2/c1
将是一个值为-1
的int
-1
对于第一个输出,我认为是正确的
对于第二个版本,通常c1*c2
结果的赋值将不适合有符号字符
,并将转换为实现定义的结果,可能-128
而不是128c1*c2
是int
乘法(标准中为5/9)。我们知道在MSVC上CHAR_位是8,并且它对有符号类型使用2的补码表示,所以我们知道值:-128*-1是128
128/-128是-1,所以这是排序的第一个结果
将-CHAR\u MIN
分配给有符号字符
有实现定义的结果(4.7/3),但我们知道在MSVC中结果是-128。然后-128/-1是1,这是第二个排序结果。c1*c2
是一个int
乘法(标准中为5/9)。我们知道在MSVC上CHAR_位是8,并且它对有符号类型使用2的补码表示,所以我们知道值:-128*-1是128
128/-128是-1,所以这是排序的第一个结果
将-CHAR\u MIN
分配给有符号字符
有实现定义的结果(4.7/3),但我们知道在MSVC中结果是-128。然后-128/-1是1,所以这是第二个排序结果。第一种情况,使向上缩放为int显式:
cout << ((int)c1 * c2 / c1 << endl;
cout第一种情况,使向上缩放为int显式:
cout << ((int)c1 * c2 / c1 << endl;
coutc1*c2
可能不涉及任何有符号整数溢出,除非平台具有大小相同的char
和int
@Charles:它没有(它是Visual Studio).c1*c2
可能不涉及任何有符号整数溢出,除非平台具有相同大小的char
和int
。@Charles:它没有(它是Visual Studio)。但是为什么c1*c2
将成为int
?这是标准吗?@Mihran因为整数promotion@MihranHovespyan:整数提升适用于*
的两个操作数,因此在执行乘法之前,两个有符号字符
都将提升为int
。尽管看起来很奇怪,但您可以用一个简单的测试程序验证这一点:void foo(int){std::cout但是为什么c1*c2
会是int
?这是标准吗?@Mihran因为整数promotion@MihranHovespyan:整数提升适用于*
的两个操作数,因此在执行乘法之前,这两个有符号字符将被提升为int
。尽管看起来很奇怪,您可以n用一个简单的测试程序来验证这一点:void foo(int){std::cout升级到int
是多余的,实现还是会这样做的
算术运算没有溢出,存在从一个整数类型到另一个整数类型的显式转换。这将是实现定义的,而不是欠定义的行为。升级到int
是多余的,实现无论如何都会这样做。在这种情况下,在(带符号字符)((int)c1*c2)中
算术运算没有溢出,而是从一个整数类型到另一个整数类型的显式转换。这是实现定义的,而不是欠定义的行为。