c - 了解 `int` 和 `long long` 变量的整数溢出

标签 c integer-overflow

为什么这些程序会产生不同的输出?

Program 1 :

#include <stdio.h>
#include <limits.h>

int main()
{
    long long bigger = 0;
    int smaller = INT_MAX;

    bigger = smaller * 2;
    printf("Smaller = %d\n", smaller);
    printf("Bigger = smaller * 2 = %lld\n\n", bigger);

    return 0;
}

输出:

Smaller = 2147483647

Bigger = smaller * 2 = -2


Program 2 :

#include <stdio.h>
#include <limits.h>

int main()
{
    long long bigger = 0;
    int smaller = INT_MAX;

    bigger = smaller;
    bigger *= 2;
    printf("Smaller = %d\n", smaller);
    printf("Bigger = smaller * 2 = %lld\n\n", bigger);

    return 0;
}

输出:

Smaller = 2147483647

Bigger = smaller * 2 = 4294967294


我的猜测是程序 1 试图将乘法结果存储在与 int 大小相同的临时存储器中。所以它溢出了。而程序 2 将乘法结果存储在较大的存储空间中。

我说的对吗?

此外,如果我在其中任何一个程序中犯了任何严重错误,请告诉我(因为根据我的说法,这些程序可以完美编译)!

最佳答案

smaller 是一个 int,文字 2 也是。所以他们的乘积也是 int。由于 INT_MAX * 2 不能用 int 表示(根据定义,差不多),它会溢出导致未定义的行为。

但是,如果您将值存储在 long long 中,则在执行乘法时,会发生默认整数提升(“通常的算术转换”)。现在,如果您的 long long 可以表示 INT_MAX * 2,您最终会得到语义上等同于 bigger = bigger * (long long)2,按预期工作。

关于c - 了解 `int` 和 `long long` 变量的整数溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21653224/

相关文章:

c - 如果不使用 C 中的逻辑运算符、关系运算符或选择结构,如何将 11,12 和 13 的值分配给所有等于 10 的值?

algorithm - 自定义溢出检测

rust - 如何在启用溢出检查的情况下编译和运行优化的 Rust 程序

javascript - 在 Python 中使用大整数模拟 JavaScript 加法错误

c - 为什么依赖溢出整数的循环在不同计算机上的工作方式不同?

c - 管道(), fork ();执行();我寻找与 bash 相同的行为 `cat | ls`

c - 当ACK丢失时,发送方和接收方都停止?

c - 有什么理由我不应该对 C 中的所有变量和函数声明使用 "volatile"关键字?

c - CUDA 中的每线程哈希表类数据结构实现

python - 用整数运算准确反射(reflect)大数和的大小