简体   繁体   中英

warning: cast from pointer to integer of different size [-Wxpointer-to-int-cast]

I have warnings when I try to compile the code. I know it has something to do with the 64-bit Architecture. But I am not able to fix it.

#define GETFUNC(x,y)    x = (void *)dlsym(hLib, y); \
                        if(!quiet) printf("  %-10s %08x\n", y, (uint32_t)x);

warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

if(!quiet) printf("  %-10s %08x\n", y, (uint32_t)x)

Well, on your system, pointers obviously are 64 bit. These do not fit into the 32-bit value you cast to, thus you get a warning.

To cast pointers to integers, you should go via uintptr_t :

printf("  %-10s %08x\n", y, (uint32_t)(uintptr_t)x);
//                 ^ however, what, if uint32_t is long on your system???
//                   coming to later...

First cast makes an integer of appropriate size from the pointer, second cast tells the compiler that you explicitly want to truncate the value – and it won't issue a warning any more as it assumes it is what you want to do.

But: You are cutting off the upper half of the address information! If you use this, you might end up in seeing two totally different variables at the same memory location, because the addresses might have differed only in upper half.

You might live with for having shorter logs ('collision' probability shouldn't be too high), the correct way, though, would be outputting via appropriate pointer format specifier %p :

printf("  %-10s %p\n", y, x);        // usually no cast needed, but actually incorrect
printf("  %-10s %p\n", y, (void*)x); // fully compliant variant

This will print all eight bytes (16 nibbles) correctly on your system, four bytes (8 nibbles) on a 32-bit system. If you want to have all eight bytes on any system (for uniform logs), then you can go via appropriate casts again:

printf("  %-10s %016llx\n", y, (uint64_t)x);
//                   ^ uint64_t most likely is unsigned long long
//                     but on 64-bit linux, just unsigned long!!!

Casting to uintptr_t is not necessary this time, as any pointer would fit into – and some time in the future, when the first 128-bit systems appear, you might even want the warning to re-appear (and if really not, add the intermediate cast again). Edit: As denoted, not fixing the warning would result in undefined behaviour, though. So to be on the safe side, you'd rather explicitly catch the issue via static_assert(sizeof(uintptr_t) <= sizeof(uint64_t)) , which would enforce adjustment (thanks, chux, for the hint).

Well, correct format specifier... Luckily, there are appropriate macros defined, although usage is not really nice:

printf("  %-10s %016" PRIx64 "\n", y, (uint64_t)(uintptr_t)x);

(would have been PRIx32 in initial example).

uint32_t = 32 bit.

Your pointer = 64 bit.

Hence the warning. You can use %p to print the pointer, or, if you want an integer, cast to size_t and use the z modifier (SO here ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM