Home > other >  How do I construct a "signed size_t" for use with scanf("%zn")?
How do I construct a "signed size_t" for use with scanf("%zn")?

Time:01-22

I tried to obtain the number of characters read as a size_t, using this program:¹

#include <stdio.h>

int main(void)
{
    size_t i;
    sscanf("abc", "%*s%zn", &i);
    printf("%zu", i);
}

GCC 12 warns about this:

scanf.c: In function ‘main’:
scanf.c:7:25: warning: format ‘%zn’ expects argument of type ‘signed size_t *’, but argument 3 has type ‘size_t *’ {aka ‘long unsigned int *’} [-Wformat=]
    7 |     sscanf("abc", "%*s%zn", &i);
      |                       ~~^   ~~
      |                         |   |
      |                         |   size_t * {aka long unsigned int *}
      |                         long int *
      |                       %ln

And it's correct² do do so; in the C17 draft standard, page 234, we read (my emphasis)

No input is consumed. The corresponding argument shall be a pointer to signed integer into which is to be written the number of characters read from the input stream so far by this call to the fscanf function.

Earlier standards contain similar wording.

So how do I (portably) create a signed equivalent of size_t for this conversion?

In C , I could use std::make_signed_t<std::size_t>, but that's obviously not an option for C code. Without that, it seems that %zn conversion is unusable in C.


¹ The real-world case from which this arises came from reviewing Simple photomosaic generator, where we wanted a more general form of strto

  • Related