在 C 中为 int 变量赋值一个大值



我知道当我将大于INT_MAX的值分配给 int 变量时会发生溢出,但如果这个值也被大数除以会发生什么? 在下面的语句中 溢出int x = 3000000000/10000;会发生?

如果表达式中的整数常量(文字)可以用 C 编译器支持的类型表示,并且具有正确的符号,则编译器将对它们执行正确的算术(由 C 标准定义)。如果结果可以用int表示,则int x = expression;将初始化x以获得该值。

如果结果无法在int中表示,则初始化的结果是实现定义的,根据C 2018 6.3.1.3 3。

如果整数常量不能以 C 编译器支持的具有正确符号的任何类型的形式表示,则 C 标准不会定义该行为,但编译器必须提供诊断消息(根据 6.4.4.1 6 和 6.4.4 3)。

您可以投射更大的数字,例如long long,然后将结果转换回 int。这应该避免任何溢出。 所以像这样:https://stackoverflow.com/a/9047811 (只是你之后会通过int result = (int)((long long)(numerator)/(long long)(denominator))将其转换回 int .

我知道

当我将大于 INT_MAX 的值分配给 int 变量时会发生溢出,

当常量在(unsigned) long long内时不会发生溢出。 相反,这是超出int范围的值的转换。 结果是定义了实现

当整数类型的值转换为_Bool以外的另一个整数类型时,如果该值可以由新类型表示,则它保持不变。
...
否则,新类型是有符号的,并且无法在其中表示该值;结果要么是实现定义的,要么是实现定义的信号。C17dr 6.3.1.3

常见的实现定义行为是删除上位。

int some_int = 0x123456789A;  // Out of range
printf("%dn"); --> possible outcome 0x3456789A as "878082202"

如果这个值也除以一个大数字会发生什么?会发生溢出吗?

不。 在这种情况下3000000000longlong long。 商的类型相同,但值为 300,000。 使用 32 位int,可以很好地转换为值为 300,000 的int

int x = 3000000000/10000; 

在这种情况下,在int x = 3000000000LL/10000;中附加LL没有区别。

在您的特定情况下:

int x = 3000000000/10000;

右侧表达式是一个常量,因此编译器 [至少gcc] 在编译时解析除法,因此结果是300000。(为此,编译器必须使用比内部int更高的精度进行常数约简)

但是,如果您这样做:

int x = 3000000000;
x /= 10000;

你得到:-129496[因此溢出]

那是因为x第一行溢出[并变为负数]。

3000000000仍然适合 32 位(无符号),因此您可以得到值0x0xb2d05e00.请注意,MSB [符号位] 已设置。

而且,当您除以10000时,除法将保留标志并产生:0xfffe0628

乍一看,这两个代码片段应该产生相同的结果。但是,他们没有,因为编译器必须遵循两步过程(即它不能将两个步骤组合在一起)。

否则,编译器会破坏其他依赖于截断等的代码:(例如舍入):

int x = 37;
x /= 10;
x *= 10;

你很幸运,因为3000000000[正如我所说]适合unsigned int.但是,如果你添加一个额外的 0(例如)30000000000,编译器将标记它:

warning: overflow in conversion from ‘long int’ to ‘int’ changes value from ‘30000000000’ to ‘-64771072’ [-Woverflow]
int x = 30000000000;
^~~~~~~~~~~

所以,你真的不应该依赖一个具体的结果,如果你已经知道你正在做一些有问题/错误的事情。


下面是一个示例程序:

#include <stdio.h>
int
print_x(void)
{
int x = 3000000000/10000;
return x;
}
int
print_y(void)
{
int y = 3000000000;
y /= 10000;
return y;
}
int
print_z(void)
{
int z = 3000000000;
return z;
}
int
print_w(void)
{
int w = 30000000000;
return w;
}
int
main(void)
{
printf("x=%dn",print_x());
printf("y=%dn",print_y());
printf("z=%dn",print_z());
printf("w=%dn",print_w());
return 0;
}

这是程序输出:

x=300000
y=-129496
z=-1294967296
w=-64771072

相关内容

最新更新