给定以下片段:

#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);
}

MINGW GCC 3.4.5的输出IS(-O0):

1
4
8
10000
-1486618624

第一个乘法在内部施放到INT32(根据汇编器输出)。第二个乘法未施放。我不确定结果是否有所不同,因为该程序在IA32上运行,或者是因为在C标准中定义了该程序。但是,如果在某个地方定义了这种确切的行为(ISO/IEC 9899?),我很感兴趣,因为我喜欢更好地理解为什么和何时手动施放(我在其他架构中移植程序问题)。

有帮助吗?

解决方案

C99标准确实指定了二进制操作员,例如 * 不要以小于整数类型的操作 int. 。这些类型的表达被提升为 int 在应用操作员之前。参见6.3.1.4第2段以及“整数促销”一词的大量出现。但这与编译器生成的汇编指令有些正交,该指令运行 intS,因为即使允许编译器计算出较短的结果,这也更快(因为结果立即存储在短类型的L值中)。

关于 int64 f = d * e; 在哪里 de 是类型 int, ,乘法作为一个 int 按照相同的晋升规则。从技术上讲溢出 不确定的行为, ,您在这里获得了两-S-conperment的结果,但是根据标准,您可以得到任何东西。

注意:促销规则在晋升时区分签名和未签名类型。规则是将较小类型推广到 int 除非 int 不能表示类型的所有值,在这种情况下 unsigned int 用来。

其他提示

问题在于乘法为INT32 * INT32,以INT32的形式完成,然后将结果分配给INT64。你会得到同样的效果 double d = 3 / 2;, ,将使用整数部门将3除以2,并将1.0分配给 d.

您必须注意表达式或子表达的类型。这需要确保将适当的操作计算为适当的类型,例如将其中一种乘以INT64或(在我的示例中) 3.0 / 2 或者 (float)3 / 2.

阅读K&R(原始)。所有整数操作均使用自然整数类型完成,除非它涉及(或铸造)到更大的变量。 Char上的操作被铸造到32位,因为这是该架构上整数的自然大小。两个32位整数的乘法是在32位完成的,因为没有什么将其铸造成更大的东西(直到将其分配给64位变量,但这为时已晚)。如果您希望该操作以64位发生,请将一个或两种int施放至64位。

int64 f = (int64)d * e;

a * b 被计算为int,然后铸造为接收变量类型(恰好是int)

d * e 被计算为int,然后铸造为接收变量类型(恰好是int64)

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top