C ++中两个整数的乘法

时间:2015-07-27 20:36:01

标签: c++ int range long-integer

我有一个非常基本的问题,但我不确定我是否理解这个概念。假设我们有:

int a = 1000000;
int b = 1000000;
long long c = a * b;

当我运行时,c显示负值,因此我也将ab更改为long long,然后一切都很好。那么,为什么我必须更改ab,当它们的值在int范围内且其产品已分配到c时(long long )?

我正在使用C / C ++

4 个答案:

答案 0 :(得分:19)

int在乘法之前不会被提升为long long,它们仍然是int s和产品。然后将产品投射到long long,但为时已晚,溢出已经发生。

拥有ab long long之一也应该有效,因为另一个会得到提升。

答案 1 :(得分:3)

对于算术运算符,结果的类型不依赖于您为结果分配的内容,而是依赖于操作数的类型。对于算术运算符,usual arithmetic conversions在操作数上执行。这用于将操作数转换为通用类型,这意味着对于小于 unsigned / signed int的类型,如果值适合,则将它们提升为 unsigned < / em> / 签名 int,在这种情况下,它们已经是int,因此不需要转换。有关原因的详细信息,请参阅Why must a short be converted to an int before arithmetic operations in C and C++?

我们现在拥有的是未定义的行为,因为有符号整数溢出是未定义的行为,这在草案C ++标准部分5 [Expr] 中有所说明:

  

如果在评估表达式期间,结果未在数学上定义或不在范围内   其类型的可表示值,行为未定义。 [注意:大多数现有的C ++实现   忽略整数溢出。除以零的处理,使用零除数形成余数,以及所有   浮点异常因机器而异,通常可通过库函数进行调整。 - 后注]

现在我们有清理器来捕获这些类型的未定义行为,并且使用-fsanitize=undefined同时使用clang和gcc将在运行时捕获此错误( see it live ):

  

运行时错误:有符号整数溢出:1000000 * 1000000不能   用类型&#39; int&#39;

表示

参考部分5.6 [expr.mul] 说:

  

[...]通常的算术转换是在操作数上执行的   并确定结果的类型。

和第5部分说:

  

否则,应对两个操作数执行整数提升(4.5).61然后执行以下操作   规则应适用于推广的操作数

     
      
  • 如果两个操作数具有相同的类型,则无需进一步转换。
  •   

答案 2 :(得分:0)

这有点荒谬,因为汇编指令总是计算

int * int - &gt; 64位长

所以,如果您查看机器代码,您会看到: 的 IMUL 将64位存储到eax edx中 然后 的 CDQ 将eax的位符号放入edx(从而失去完整的64位结果) 然后将eax edx存储到64位变量

如果在乘法之前将32位值转换为64位,则无条件地调用64位乘法函数

(我检查过:代码优化时并非如此)

答案 3 :(得分:-1)

指针乘法

定义一个乘法函数,它将两个指针变量作为参数,然后返回指针。从主调用这个函数

 #include<iostream>
 using namespace std;

 int *multiply(int *x,int* y)
 {
     int  mul;      
     mul = (*x)*(*y); 
     int *c; 
     c = &mul;        
     return c;            
  }


int main()
{

int x,y;
x = 4;
y = 5;
int *result;         
result = multiply(&x,&y);
cout<<*result<<endl;

return 0;

}