如何使变量不超过其类型的大小限制

how to make a variable not exceed the size limit of its type?

本文关键字:类型 何使 变量 不超过      更新时间:2023-10-16

所以我想知道如何使变量不超过其数量限制。

例如:

int x;

x的大小是四个字节的

由于已签名,它从(−2147483648)开始到(2147483647)

因此,如果输入大于2147483647,它将不会注册,我想防止程序让大于其数字限制的数字输入

这里有一个代码会遇到这个问题:

int x[3];
x[0] = 12;
x[1] = 642;
x[2] = 800000000;
for (int z = 0;z < 3;z++)
{
        x[z] = x[z] * 3;

}

那么,如果结果大于变量类型的数量限制,我将如何防止x[z]将其自身乘以3呢?

可移植且明显但不令人满意的答案是,您必须事先检查操作数:

int x[3];
x[0] = 12;
x[1] = 642;
x[2] = 800000000;
for (int z = 0; z < 3; z++)
{
    if (x[z] < std::numeric_limits<int>::max() / 3 &&
        x[z] > std::numeric_limits<int>::min() / 3) 
    {
        x[z] = x[z] * 3;
    } else {
        std::cout << "Error" << std::endl;
    }
}

不幸的是,当溢出发生时/发生后,没有可移植的内置工具来检测/防止溢出,但你可以查看clang的消毒程序(我相信还有gcc)。它们基本上会通过这些检查自动检测你的代码,例如,如果发生溢出,则终止程序。

如果只想在调试模式下进行这些检查,则可以将它们作为assert语句的一部分而不是if语句来执行。

您要查找的单词是"溢出"。

自GCC 5以来,有一些内置程序可以检测到这一点:https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html

对于以前的版本,您必须找到另一个实现——可能有polyfill。

对于秩大于或等于int的有符号整数,也可以使用-fsanitize=signed-integer-overflow进行编译。

编辑:如果输出和两个输入都是相同的类型,那么LKML上有一个补丁:https://lkml.org/lkml/2015/7/19/358

这很好地涵盖了主题。然而,如果你想要一个快速而肮脏的解决方案,你总是可以得到双倍的结果,四舍五入,并检查它是否会导致溢出。如果没有,则强制转换为integer并使用它。如果有,则可以抛出错误,例如:

#include <iostream>
#include <cassert>
#include <limits>
using namespace std;
int main()
{
    int xOriginal=1000000000;
    int xFinal=0;
    for (int i=0;i<1000;++i){
        double temp_result=i*(double)xOriginal;
        if (temp_result<std::numeric_limits<int>::max()
            && temp_result>std::numeric_limits<int>::min()){
            xFinal=(int)temp_result;
            cout <<"new x is : "<<xFinal <<endl;
        }else{
            assert(!"Integer overflow");
        }
    }
}

此代码的输出为:

new x is : 0
new x is : 1000000000
new x is : 2000000000
a.out: test6.cpp:19: int main(): Assertion `!"Integer overflow"' failed.