[英]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.
我知道这与 64 位架构有关。 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.好吧,在您的系统上,指针显然是 64 位的。 These do not fit into the 32-bit value you cast to, thus you get a warning.
这些不适合您投射到的 32 位值,因此您会收到警告。
To cast pointers to integers, you should go via uintptr_t
:要将指针转换为整数,您应该通过
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
:您可能会接受较短的日志(“碰撞”概率不应太高),但正确的方法是通过适当的指针格式说明符
%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.这将在您的系统上正确打印所有八个字节(16 个半字节),在 32 位系统上打印四个字节(8 个半字节)。 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).这次没有必要
uintptr_t
为uintptr_t
,因为任何指针都适合——而且在未来的某个时间,当第一个 128 位系统出现时,您甚至可能希望重新出现警告(如果真的没有,请添加再次中间投)。 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).因此,为了安全起见,您宁愿通过
static_assert(sizeof(uintptr_t) <= sizeof(uint64_t))
明确捕获问题,这将强制进行调整(感谢 chux 的提示)。
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). (在初始示例中应该是
PRIx32
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.