如果LONG_MAX为2147483647,strtol(“-2147483648",0,0)是否溢出? [英] Does strtol("-2147483648", 0, 0) overflow if LONG_MAX is 2147483647?

查看:288
本文介绍了如果LONG_MAX为2147483647,strtol(“-2147483648",0,0)是否溢出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据strtol的规范:

如果主题序列具有预期的形式,并且base的值是0,则将从第一个数字开始的字符序列应解释为整数常量.如果主题序列具有预期的形式,并且base的值在2到36之间,则应将其用作转换的基础,将每个字母的值如上所述.如果主题序列以减号开头,则转换结果应为负.如果endptr不是空指针,则指向最终字符串的指针应存储在endptr指向的对象中.

If the subject sequence has the expected form and the value of base is 0, the sequence of characters starting with the first digit shall be interpreted as an integer constant. If the subject sequence has the expected form and the value of base is between 2 and 36, it shall be used as the base for conversion, ascribing to each letter its value as given above. If the subject sequence begins with a minus-sign, the value resulting from the conversion shall be negated. A pointer to the final string shall be stored in the object pointed to by endptr, provided that endptr is not a null pointer.

当前的问题是,在求反之前,该值不在long的范围内.例如,在C89(整数常量不能采用类型long long的情况)中,写入-2147483648可能溢出.您必须写(-2147483647-1)或类似的文件.

The issue at hand is that, prior to the negation, the value is not in the range of long. For example, in C89 (where the integer constant can't take on type long long), writing -2147483648 is possibly an overflow; you have to write (-2147483647-1) or similar.

由于使用整数常量"的措辞可以解释为对整数常量的类型应用C规则,因此这足以使我们摆脱未定义的行为,但存在相同的问题(没有这么容易的答案)将适用于strtoll.

Since the wording using "integer constant" could be interpreted to apply the C rules for the type of an integer constant, this might be enough to save us from undefined behavior here, but the same issue (without such an easy out) would apply to strtoll.

最后,请注意,即使确实溢出,也应返回正确"的值.因此,这个问题实际上只是关于在这种情况下是否可以设置errno.

Finally, note that even if it did overflow, the "right" value should be returned. So this question is really just about whether errno may or must be set in this case.

推荐答案

尽管我现在无法指出标准中的特定用语,但是当我在1990年代为4BSD编写strtol时,我很确定应该 not 设置errno,并确保我不会.无论是基于标准中的措辞还是与某人的私人讨论,我都不再记得.

Although I cannot point to a particular bit of wording in the standard today, when I wrote strtol for 4BSD back in the 1990s I was pretty sure that this should not set errno, and made sure that I would not. Whether this was based on wording in the standard, or personal discussion with someone, I no longer recall.

为了避免溢出,这意味着必须非常小心地进行计算.我在unsigned long中做到了,并包含了此注释(仍在各个BSD的libc源代码中):

In order to avoid overflow, this means the calculation has to be done pretty carefully. I did it in unsigned long and included this comment (still in the libc source in the various BSDs):

    /*
     * Compute the cutoff value between legal numbers and illegal
     * numbers.  That is the largest legal value, divided by the
     * base.  An input number that is greater than this value, if
     * followed by a legal input character, is too big.  One that
     * is equal to this value may be valid or not; the limit
     * between valid and invalid numbers is then based on the last
     * digit.  For instance, if the range for longs is
     * [-2147483648..2147483647] and the input base is 10,
     * cutoff will be set to 214748364 and cutlim to either
     * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
     * a value > 214748364, or equal but the next digit is > 7 (or 8),
     * the number is too big, and we will return a range error.
     *
     * Set 'any' if any `digits' consumed; make it negative to indicate
     * overflow.
     */

C库中的此操作与语言本身的语法(其中负数是两个单独的标记,-后跟数字)之间的不对称性使我(在某种程度上仍然感到恼怒)表示-217483648意味着-(217483648)变成-(217483648U)当然是217483648U并因此是肯定的!(当然,假设32位int;问题值会随其他位大小而变化)

I was (and still am, to some extent) annoyed by the asymmetry between this action in the C library and the syntax of the language itself (where negative numbers are two separate tokens, - followed by the number, so that writing -217483648 means -(217483648) which becomes -(217483648U) which is of course 217483648U and hence positive! (Assuming 32-bit int of course; the problematic value varies for other bit sizes.)

这篇关于如果LONG_MAX为2147483647,strtol(“-2147483648",0,0)是否溢出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆