Using size_t to indicate string precision in C printf

I have a structure for representing lines in memory that look like this:

typedef struct { size_t l; char *s; } str_t; 

I believe that using size_t makes sense to indicate the length of the char string. I would also like to print this line using printf("%.*s\n", str.l, str.s) . However, precision * expects an int argument, not size_t . I could not find something important in this matter. Is it possible to somehow use this structure correctly, without casting to int in the printf() call?

+6
source share
3 answers

You can make a macro

 #define STR2(STR) (int const){ (STR).l }, (char const*const){ (STR).s } 

and then use this as printf("%.*s\n", STR2(str)) .

Beware that this evaluates to STR twice, so be careful with the side effects, but you probably already knew that.

Edit:

I use complex initializers, so these are implicit conversions. If everything goes wrong, there is more chance that the compiler will warn you than with an explicit cast.

For example, if STR has a .l field that is a pointer, and you just put the cast in int , all compilers would happily convert that pointer to int . Similarly, for the .s field, it really should match char* or something compatible, otherwise you will see a warning or error.

+3
source
 printf("%.*s\n", (int)str.l, str.s) // ^^^^^ use a type cast 

Edit

Well, I didn’t read the question correctly. You do not want to use a type, but I think in this case: hard.

Either that, or just use fwrite

 fwrite(str.s, str.l, 1, stdout); printf("\n"); 
+5
source

There is no guarantee that size_t is an int, or that it can be represented inside an int. This is just part of the C legacy that does not determine the exact size of the int, combined with fears that the size_t implementation may need to be used to solve large areas of memory (those that have more MAX_INT values ​​in them).

The most common error regarding size_t is to assume that it is equivalent to an unsigned int. Such old errors were common, and from personal experience, he suffers from 32-bit to 64-bit architecture, since you need to cancel this assumption.

At best, you can use a throw. If you really want to get rid of the cast, you can also opt out of using size_t.

+1
source

Source: https://habr.com/ru/post/901223/


All Articles