我试图在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
我错过了什么?
答案 0 :(得分:6)
如果您不想要溢出效果,请不要使用该功能的已签名变体。请改用strtoul()
。
使用以下代码:
#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;
}
我明白了:
Conversion results of string: 0xffff1234
strtoul signed = -60876
strtoul unsigned = 4294906420
在调用strtol()
及其兄弟时,您无法控制此行为,因为行为 这些函数。标准有这样说:
strtol,strtoll,strtoul和strtoull函数返回转换后的值(如果有)。如果无法执行转换,则返回零。如果正确的值超出可表示值的范围,则返回LONG_MIN,LONG_MAX,LLONG_MIN,LLONG_MAX,ULONG_MAX或ULLONG_MAX(根据值的返回类型和符号,如果有),并且宏ERANGE的值为存储在errno。
答案 1 :(得分:3)
long
的最小范围是-2147483647到2147483647.您实施的long
范围可能是-2147483648到2147483647.
strtol()
的定义表示如果转换后的值超出long
的范围,则会根据转换后的值的符号返回LONG_MIN
或LONG_MAX
,ERANGE
存储在errno
中。在这种情况下,转换后的值0xffff1234
超出了范围 - 它大于LONG_MAX
,因此会返回LONG_MAX
。
顺便说一下,您对sscanf()
的调用会覆盖n
中转换后的值,返回值为sscanf()
,该值为1,表示转换成功1次。