如果我执行以下操作:
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位)
答案 0 :(得分: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
类型的临时表中。任何表达式的结果都以最高精度投射到其成员的精度。
在第一个示例中,int
足以保存乘以char
s的结果,因此没有溢出。
作为旁注,建议不要命名变量ll
,因为很难区分数字'1'和小写字母'l'。
答案 1 :(得分: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
因此,对于带有签名char
的系统,最后两行有效,这意味着当您在代码中编写CHAR_MAX时,编译器会看到一个类型为{{1}的平面127 }。
这意味着乘法int
* CHAR_MAX
以CHAR_MAX
精度发生。
答案 2 :(得分:0)
除非指定了明确的类型转换,否则任何表达式都会被转换为所涉及的最高精度变量/常量的精度。
正如彼得指出的那样,在表达式中使用明确的类型转换来强制更高的精确度。
注意:我没有得到“long long int”部分。也许这是很长时间,因为我看到了......; - )
- long long int 是否真的声明了64位int?
哪个编译器使用??