sscanf和%i /大无符号整数的基数检测

时间:2020-05-24 20:07:59

标签: c scanf unsigned unsigned-integer

我正在处理包含大量数字(磁盘偏移量)的文件,并且在scanf中使用%lli遇到了问题-数字的格式为0x ...但是scanf不会读取所有位。

这是示例代码(我在https://www.onlinegdb.com/online_c_compiler上进行了测试)。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char* str = malloc(30);
    unsigned long long l;
    sprintf(str, "0x%llx\n", 0xffffffffffffffffULL);
    printf("%s\n", str);
    sscanf(str, "%lli", &l);
    printf("%llx\n", l);

    return 0;
}

它输出:

0xffffffffffffffff

7fffffffffffffff

我希望两个数字相等。

如果我使用%llx指示符,它可以正常工作,但是我不想将自己限制为十六进制格式的数字。

2 个答案:

答案 0 :(得分:3)

不幸的是,i代表 signed 整数,并且相应的预期参数是指向int的指针;使用ll的宽度将为long long,但仍将被签名。对于带有基本检测的无符号整数,没有scanf格式字符。


没有完美的解决方案。您可以使用strtoull(str, &endptr, 0)(甚至是strtoumax),它可以正确检测格式,但是使用起来比较麻烦。

但是scanf也不是完美的-如果数字太大,则总是会得到最大值,就像得到LLONG_MAX一样,没有错误指示。

答案 1 :(得分:-1)

cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core) gcc --version gcc (GCC) 8.3.1 20190507 (Red Hat 8.3.1-4) autoreconf --version autoreconf (GNU Autoconf) 2.69 用于%lli(在您的系统上,该数字最多只能为0x7fffffffffffffff)。

long long signed int用于%llu(这是您要阅读的内容)。

将前者替换为后者。