3

编译器将源代码作为字符串处理,因此在 C++ 中,例如,当它鼓励像它从必须在和之间的范围内unsigned char x = 150;的类型限制中知道的语句一样时。unsigned char0255

我的问题是,虽然数字150仍然是字符串,但算法编译器使用什么算法编译器来比较数字序列 -150在这种情况下 - 与类型限制?

我为十进制、八进制、十六进制和小端二进制的“int”类型做了一个简单的算法,但我不认为编译器会做这样的事情来检测数字溢出。

我制作的算法是用 C++ 编码的:

typedef signed char int8;
typedef signed int  int32;

#define DEC  0
#define HEX  1
#define OCT  2
#define BIN  3

bool isOverflow(const char* value, int32 base)
{
    // left-most digit for maximum and minimum number
    static const char* max_numbers[4][2] =
    {
        //                 INT_MAX                           INT_MIN
        {                       "2147483647",                       "2147483648" }, // decimal
        {                         "7fffffff",                         "80000000" }, // hexadecimal
        {                      "17777777777",                      "20000000000" }, // octal
        { "01111111111111111111111111111111", "10000000000000000000000000000000" }  // binary
    };

    // size of strings in max_numbers array
    static const int32 number_sizes[] = { 10, 8, 11, 32 };

    // input string size
    int32 str_len = strlen(value);

    // is sign mark exist in input string
    int32 signExist = ((base == DEC || base == OCT) && *value == '-');

    // first non zero digit in input number
    int32 non_zero_index = signExist;

    // locate first non zero index
    while(non_zero_index < str_len && value[non_zero_index] == 0) non_zero_index++;

    // if non_zero_index equal length then all digits are zero
    if (non_zero_index == str_len) return false;

    // get number of digits that actually represent the number
    int32 diff = str_len - non_zero_index;

    // if difference less than 10 digits then no overflow will happened
    if (diff < number_sizes[base]) return false;
    // if difference greater than 10 digits then overflow will happened
    if (diff > number_sizes[base]) return true;

    // left digit in input and search strings
    int8 left1 = 0, left2 = 0;

    // if digits equal to 10 then loop over digits from left to right and compare
    for (int32 i = 0; non_zero_index < str_len; non_zero_index++, i++)
    {
        // get input digit
        left1 = value[non_zero_index];
        // get match digit
        left2 = max_numbers[signExist][i];

        // if digits not equal then if left1 is greater overflow will occurred, false otherwise
        if (left1 != left2) return left1 > left2;
    }

    // overflow won't happened
    return false;
}

该算法可以优化为适用于所有整数类型,但对于浮点,我必须制作新的算法才能使用 IEEE 浮点表示。

我认为编译器使用有效的算法来检测我以外的溢出,不是吗?

4

5 回答 5

6

编译器以最简单的方式处理它:他们将数字转换为整数或适当的浮点数。没有法律规定编译器不能将字符串转换为其他适当的表示形式。

但是现在,考虑一下你原来的问题;如果您获取数字并构建例程将它们视为数字怎么办?比如说,一个算法可以采用

6+5

并将总和计算为两位数的字符串11?将其扩展到其他操作,您可以直接计算是否 32769大于32768

于 2011-06-01T23:09:50.500 回答
1

编译器似乎最简单的做法是一步将字符串表示形式转换为整数,然后在第二步中与类型的上限和下限进行比较。

我无法想象为什么比较字符串会更好。

对于浮点数,由于精度和舍入,问题更加困难。

于 2011-06-01T23:11:21.560 回答
0

我不确定大多数编译器采用什么特定算法来执行此操作,但这里有一些可行的选项:

  1. 编译器可以尝试使用现有库(例如,在 C++ 中,a stringstream)尝试将字符串转换为适当类型的数字。然后可以使用它来检查错误。

  2. 编译器可以将字符串转换为非常高精度的数字格式(例如,128 位整数),然后在将数字文字分配给原始类型时检查该值是否适合该范围没有演员表。

于 2011-06-01T23:12:19.127 回答
0

看到编译器无论如何都必须转换为整数/数字类型,他们也可以让他们的atoi, atol,atof函数在超过目标容量时引发错误。

无需事先对字符串进行操作,并在单独的步骤中进行转换。

我认为,最有可能的是,编译器会直接在其(高度优化的)解析器的语义操作中转换为整数类型。

于 2011-06-01T23:14:25.423 回答
0

在大多数编译器理论中,程序(翻译单元)的文本被转换为标记。例如,文本“150”将被转换为值为 150 的常量整数标记。这当然是在预处理器运行之后。

然后编译器开始语法和语义检查过程。因此,对赋值语句进行语法评估(正确的拼写和格式),然后检查语义。

编译器可以抱怨超出范围的值(例如 -150 unsigned char)或应用一些转换。在 -150 的情况下,这将被转换为 8 位值(指示负值的最高有效位现在是值 128)。我不是语言律师,所以我不完全了解编译器在这方面的自由度,也不知道是否需要警告。

总之,编译器在评估语句和检查语义时有一些自由度。所有文本都转换为标记和值的内部表示(更紧凑的数据结构)。在编译过程的语义阶段检查常量整数文字是否在赋值语句的范围内。语义由语言标准或公司政策决定。一些语义被转化为编译器选项并留给程序员。

于 2011-06-01T23:25:50.167 回答