2

我正在尝试在 32 位机器上进行十六进制到整数的转换。这是我正在测试的代码,

int main(int argc,char **argv)
{
    char *hexstring = "0xffff1234";
    long int n;

    fprintf(stdout, "Conversion results of string: %s\n", hexstring);
    n = strtol(hexstring, (char**)0, 0); /* same as base = 16 */
    fprintf(stdout, "strtol = %ld\n", n);
    n = sscanf(hexstring, "%x", &n);
    fprintf(stdout, "sscanf = %ld\n", n);
    n = atol(hexstring);
    fprintf(stdout, "atol = %ld\n", n);
    fgetc(stdin);

    return 0;
  }

这就是我得到的:

 strtol = 2147483647 /* = 0x7fffffff -> overflow!! */
 sscanf = 1 /* nevermind */
 atol = 0   /* nevermind */

如您所见,使用 strtol 时出现溢出(我还检查了 errno),尽管我希望不会发生任何事情,因为 0xffff1234 是一个有效的 32 位整数值。我要么期望 4294906420 要么 -60876

我错过了什么?

4

2 回答 2

6

If you don't want the overflow effect, don't use the signed variant of the function. Use strtoul() instead.

With the following code:

#include <stdio.h>
int main(int argc,char **argv) {
    char *hexstring = "0xffff1234";
    long sn;
    unsigned long un;

    fprintf(stdout, "Conversion results of string: %s\n", hexstring);

    sn = strtoul(hexstring, (char**)0, 0);
    fprintf(stdout, "strtoul   signed = %ld\n", sn);

    un = strtoul(hexstring, (char**)0, 0);
    fprintf(stdout, "strtoul unsigned = %lu\n", un);

    return 0;
}

I get:

Conversion results of string: 0xffff1234
strtoul   signed = -60876
strtoul unsigned = 4294906420

You cannot control this when calling strtol() and its brethren since the behaviour is within those functions. The standard has this to say:

The strtol, strtoll, strtoul, and strtoull functions return the converted value, if any. If no conversion could be performed, zero is returned. If the correct value is outside the range of representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, or ULLONG_MAX is returned (according to the return type and sign of the value, if any), and the value of the macro ERANGE is stored in errno.

于 2012-07-24T09:47:13.400 回答
3

的最小范围long是 -2147483647 到 2147483647。long您的实现范围可能是 -2147483648 到 2147483647。

的定义strtol()表示如果转换后的值超出 的范围longLONG_MIN或者LONG_MAX根据转换后的值的符号返回,并ERANGE存储在 中errno。在这种情况下,转换后的值0xffff1234超出范围 - 它大于LONG_MAX,因此LONG_MAX返回。

顺便说一句,您的调用是用 的返回值sscanf()覆盖转换后的值,即 1 表示有 1 次成功转换。nsscanf()

于 2012-07-24T10:08:06.003 回答