为什么long long int不会溢出?

why doesn't long long int overflow?

long long int a;
scanf("%lld",&a);
printf("n : %lld\n",a);

输入是9223372036854775808 (LLONG_MAX + 1)

但输出是9223372036854775807 (LLONG_MAX)

x64 GNU/Linux 并且我使用 GCC 编译器

有符号溢出是未定义的行为。任何事情都有可能发生。

scanf 中的溢出会触发未定义的行为。

但是,scanf 的许多流行实现在内部使用 strto... 组中的函数将字符串转换为实际数字。 (或者,更准确地说,它们使用与 strto... 函数相同的低级实现原语。)strto... 函数在溢出时生成目标类型的最大值。该实现的副作用是您在测试中观察到的。显然使用了 strtoll,这会在正溢出时产生 LLONG_MAX

但是你不应该依赖它,因为行为是未定义的。

这是一个未定义的行为。在这里,如果您将该值分配给变量而不是获取 从输入,那个时候你会在编译时得到警告。

因为 scanf 将输入限制在有效范围内,但会引发 ERANGE 错误,如 this question and in the manpage:

中的回答

The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set indicate the error.

...

ERANGE The result of an integer conversion would exceed the size that can be stored in the corresponding integer type.

请注意,此行为不是语言或 POSIX 标准所要求的,但对于许多标准库实现(包括您的实现)来说显然是正确的。

输出将不可预测。 我用简单的 int 尝试了同一段代码。 我附上了输出。