Search code examples
cscanfunsignedunsigned-integer

sscanf and %i / radix detection of large unsigned integers


I'm working with files containing large numbers (disk offsets) and have run into a problem using scanf for %lli - the numbers are of the format 0x... but scanf doesn't read all the bits.

Here's example code (I tested on 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;
}

It outputs:

0xffffffffffffffff

7fffffffffffffff

whereas I expect both numbers to be equal.

If I use the %llx specifier, it works properly, but I don't want to limit myself to hex-formatted numbers.


Solution

  • Unfortunately i stands for signed integer, and the corresponding expected argument is a pointer to int; with ll the width will be long long, but it would still be signed. There is no scanf format character for unsigned integer with base detection.


    There is no perfect solution. You can use strtoull(str, &endptr, 0) (or even strtoumax), which will detect the format correctly, but it is much more tedious to use.

    But scanf is not perfect either - if the number is too big, then you would always get the maximum value, just like you got LLONG_MAX, without error indication.