2011-06-01 74 views
3

编译器将源代码作为字符串处理,所以在C++中,例如当它鼓励类似于unsigned char x = 150;的语句时,它从类型限制知道unsigned char必须在0255之间的范围内。编译时编译器如何检测数字溢出?

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

我做了一个简单的算法来做到这一点为十进制,八进制,十六进制和little endian二进制类型“诠释”,但我不认为编译器做这种事一样,检测数字溢出。

我提出的算法进行编码,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浮点表示工作。

我觉得编译器使用高效的算法来检测比我其他的溢出,不是吗?

+0

绝对....! – spender 2011-06-01 23:10:13

+0

以字符串形式比较数字对于大多数计算机来说不是一种有效的方法;他们更喜欢他们的数字不是文字形式。通常,大多数应用程序将数字文本转换为内部数字,然后处理内部数字。处理器像内部格式的数字,并且特别擅长以这种方式处理它们。 – 2011-06-01 23:28:13

+0

词法分析器检测到一个数字,所以它从它的后缀知道它的类型,现在它存储文字形式并将其转换为数字形式,我的问题是它将存储数字的类型是什么?以及它如何检测转换的数字与文字形式的数字相匹配? – 2011-06-01 23:37:22

回答

6

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

但现在,考虑你的原始问题;如果你把数字和建立的例程作为数字来对待它们,那么呢?说,例如,一种算法,可以采取

6 + 5

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

+0

只要没有后缀,只要没有后缀,C++数字就是'int',所以如果我执行INT_MAX + INT_MAX,那么编译器在将结果截断为目标类型限制之前将用于存储结果的存储是什么? – 2011-06-01 23:27:12

+2

好,更大。但是你不需要这么做就可以知道'INT_MAX' +'INT_MAX'>'INT_MAX'。有很多选择,其中一些决定可能取决于底层硬件;例如,有没有办法检测溢出?如果你坚持要求,我们可以对BigNum实施某种操作,交易空间和性能,以保证不会有实际溢出的机会。另外,在C++中,你不能保证编译器甚至会检测到溢出 - 编译器可以处理它的一种方式是把责任交给你。 – 2011-06-01 23:37:34

+0

谢谢你查理。 – 2011-06-02 00:17:25

1

似乎简单的编译器将字符串表示转换成一个整数在一个步骤中,然后比较针对所述类型的上界和下界中的二次工序。

我想不通为什么它会更好,比较字符串。

对于浮标,问题是更难由于精度和舍入。

0

我不知道最标准者使用要做到这一点有什么特别的算法,但这里有几个选项可以工作:

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

  2. 编译器可以将字符串转换为非常高精度的数字格式(例如,128位整数),然后检查每当从数字文字分配给基元类型时,可以在没有演员的情况下适应该范围。

+0

广告1.实际上并不存在许多已知速度较慢的选项... :) – sehe 2011-06-01 23:17:31

0

眼看编译器将不得不转换为积分/数字类型,无论如何,他们可以一样好让​​自己atoiatolatof函数产生一个错误当目标能力得到突破。

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

我认为,编译器很可能会直接在其高度优化的解析器的语义操作中转换为整型。