CCJ
CCJ

Reputation: 1719

GCC format string error oscillates between two 'format specifies ... but the argument has type ...' values, doesn't like either one

I'm running into a strange compilation issue: the code

typedef struct {
unsigned int         len;
unsigned char          value[1];
} __attribute__((packed)) value_t; 
typedef struct {
unsigned int         len;
unsigned char          msg_type;
unsigned short         ret_val;
unsigned long long         timestamp;
value_t         working_val;
} __attribute__((packed)) resp_t;
...
logd("sizeof(resp_t) = %u", sizeof(resp_t));
// logd macro expands to __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)

produces the error:

error: format specifies type 'unsigned int' but the argument has type 'unsigned long'

That seems odd since the packed struct compiled for arm64 Android should only be 28 bytes (I think), which easily fits in an unsigned integer so I would expect sizeof to return an unsigned integer type. Even if they weren't packed I'd expect sizeof to return an unsigned integer type to contain them, since they're pretty minimal structs. Anyway, I switched the code to be:

logd("sizeof(resp_t) = %lu", sizeof(resp_t));

and now I see the reverse error:

 error: format specifies type 'unsigned long' but the argument has type 'unsigned int'

Switching the code back produces the original error again. What's going on here?

Upvotes: 4

Views: 186

Answers (1)

bogdan tudose
bogdan tudose

Reputation: 1276

You can use %z

logd("%zu\n", sizeof(x)); /* for size_t */
logd("%zd\n", sizeof(x)); /* for ssize_t */ 

%z was added in C99. In case you are using MSVC which doesn't support any of the later C standards the correct prefix for size_t the correct prefix is %Iu

Edit: As @Weather Vane correctly pointed MSVC now supports %Iu. The subject was also treated here

Upvotes: 4

Related Questions