0

如果我执行以下操作:

int c0 = CHAR_MAX; //8 bit
int c1 = CHAR_MAX; //8-bit
int i = c0*c1; //store in 32-bit variable
printf("%d\n", i); //prints 16129

我们可以看到将 8 位数字相乘并产生 32 位输出没有问题。

但是,如果我这样做

int i0 = INT_MAX; //32-bit
int i1 = INT_MAX; //32 bit variable
long long int ll = i0*i1; //store in 64-bit variable
printf("%lld\n", ll); //prints 1..overflow!!

在这种情况下,两个 32 位变量相乘,溢出,然后分配给 64 位变量。

那么为什么在乘以整数而不是字符时会发生这种溢出呢?它是否取决于我机器的默认字长?(32 位)

4

3 回答 3

3

您应该更改第二个代码示例,例如

int i0 = INT_MAX; //32-bit
int i1 = INT_MAX; //32 bit variable
long long ll = ((long long)i0)*i1; //compute and store in 64-bit variable
printf("%lld\n", ll);

也就是说,在将整数相乘之前,将整数(至少其中一个)转换为 64 位。int否则会发生溢出,因为在将结果分配给long long变量之前尝试将结果存储在临时类型中。任何表达式的结果都以最高精度转换为其成员的精度。

在第一个示例中,anint大到足以容纳乘以chars 的结果,因此没有溢出。

附带说明一下,不建议为变量命名ll,因为很难区分数字“1”和小写字母“l”。

于 2010-04-19T11:11:09.343 回答
1

您对正在发生的事情的解释存在逻辑错误。

至少在 Linux 系统上,CHAR_MAX肯定不是 8 位数字。这是一个(或多或少)普通的预处理器定义,如下所示:

#  define SCHAR_MAX     127

/* Maximum value an `unsigned char' can hold.  (Minimum is 0.)  */
#  define UCHAR_MAX     255

/* Minimum and maximum values a `char' can hold.  */
#  ifdef __CHAR_UNSIGNED__
#   define CHAR_MIN     0
#   define CHAR_MAX     UCHAR_MAX
#  else
#   define CHAR_MIN     SCHAR_MIN
#   define CHAR_MAX     SCHAR_MAX
#  endif

因此,对于带有 signed chars 的系统,最后两行有效,这意味着当您在代码中编写 CHAR_MAX 时,编译器会看到一个普通的 127,它的类型为int

这意味着乘法CHAR_MAX*CHAR_MAX发生在int精度上。

于 2010-04-19T11:26:47.107 回答
0

类型转换的工作原理...


除非指定显式类型转换,否则任何表达式都会被类型转换为所涉及的最高精度变量/常量的精度。

正如彼得指出的那样,在表达式中使用显式类型转换来强制更高的精度。

注意:我没有得到“long long int”部分。也许我已经很久没有看到... ;-)

  • long long int真的声明一个 64 位的 int 吗?

你用的是哪个编译器??

于 2010-04-19T11:17:03.527 回答