Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 长与整数乘法_C_Multiplication_Long Long - Fatal编程技术网

C 长与整数乘法

C 长与整数乘法,c,multiplication,long-long,C,Multiplication,Long Long,给出以下代码段: #include <stdio.h> typedef signed long long int64; typedef signed int int32; typedef signed char int8; int main() { printf("%i\n", sizeof(int8)); printf("%i\n", sizeof(int32)); printf("%i\n", sizeof(int64)); int8 a =

给出以下代码段:

#include <stdio.h>

typedef signed long long int64;
typedef signed int int32;
typedef signed char int8;

int main()
{
    printf("%i\n", sizeof(int8));
    printf("%i\n", sizeof(int32));
    printf("%i\n", sizeof(int64));

    int8 a = 100;
    int8 b = 100;
    int32 c = a * b;
    printf("%i\n", c);

    int32 d = 1000000000;
    int32 e = 1000000000;
    int64 f = d * e;
    printf("%I64d\n", f);
}

第一次乘法在内部被强制转换为int32(根据汇编程序的输出)。第二次乘法不是强制的。我不确定结果是否不同,是因为程序运行在IA32上,还是因为它是在C标准的某个地方定义的。尽管如此,我还是对这个确切的行为是否定义在某个地方(ISO/IEC 9899?)感兴趣,因为我想更好地理解为什么以及何时必须手动强制转换(我在从不同的体系结构移植程序时遇到问题)。

问题是乘法是int32*int32,它是作为int32执行的,然后将结果分配给int64。如果
double d=3/2,您将获得大致相同的效果,它将使用整数除法将3除以2,并将1.0分配给
d


无论何时,都必须注意表达式或子表达式的类型。这需要确保将适当的操作计算为适当的类型,例如将被乘数之一转换为int64,或者(在我的示例中)
3.0/2
(float)3/2
a*b
计算为int,然后转换为接收变量类型(恰好是int)

d*e
计算为int,然后转换为接收变量类型(正好是int64)

如果其中任何一个类型变量大于int(或浮点),则将使用大于该类型的变量。但由于乘法器中使用的所有类型都是int或更小,因此使用了int。

阅读K&R(原始版本)。所有整数操作都是使用自然整数类型完成的,除非它涉及(或被转换)到更大的变量。对char的操作被强制转换为32位,因为这是该体系结构上整数的自然大小。两个32位整数的乘法是在32位中完成的,因为没有任何东西将其转换为更大的值(除非您将其分配给64位变量,但这太晚了)。如果希望操作以64位进行,请将一个或两个int强制转换为64位

int64 f = (int64)d * e;

C99标准确实规定了诸如
*
之类的二进制运算符不能对小于
int
的整数类型进行操作。在应用运算符之前,这些类型的表达式将升级为
int
。见6.3.1.4第2段和多次出现的“整数提升”一词。但这与编译器生成的汇编指令有些正交,编译器在
int
s上运行,因为即使允许编译器计算较短的结果(例如,因为结果立即存储在较短类型的l值中),汇编指令也会更快

关于
int64 f=d*e
如果
d
e
属于
int
类型,则根据相同的提升规则将乘法作为
int
进行。溢出在技术上是未定义的行为,您在这里得到的是两个s-补码结果,但是您可以根据标准得到任何结果


注意:升级规则在升级时区分有符号和无符号类型。规则是将较小的类型升级为
int
,除非
int
不能表示该类型的所有值,在这种情况下,使用
无符号int

说得很好@azraiyl应将该行更改为
int64f=(int64)d*eint
,如果它们是较小的类型。只要看一眼C99标准,就会发现情况已经不是这样了,但我并不确定。您使用的是什么C编译器,如果适用,使用哪些选项?
int64 f = (int64)d * e;