当我尝试编译代码时出现警告。我知道这与 64 位架构有关。但我无法修复它。
#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)
最佳答案
嗯,在你的系统上,指针显然是 64 位的。这些不适合您转换为的 32 位值,因此您会收到警告。
要将指针强制转换为整数,您应该通过 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...
第一次转换从指针生成一个适当大小的整数,第二次转换告诉编译器您明确想要截断该值 - 并且它不会再发出警告,因为它假设这是您想要做的。
但是:您正在切断地址信息的上半部分!如果您使用它,您最终可能会在同一内存位置看到两个完全不同的变量,因为地址可能仅在上半部分有所不同。
您可能会接受较短的日志(“冲突”概率不应太高),但正确的方法是通过适当的指针格式说明符 %p
输出:
printf(" %-10s %p\n", y, x); // usually no cast needed, but actually incorrect
printf(" %-10s %p\n", y, (void*)x); // fully compliant variant
这将在您的系统上正确打印所有八个字节(16 个半字节),在 32 位系统上打印四个字节(8 个半字节)。如果您想在任何系统上拥有所有八个字节(用于统一日志),那么您可以再次进行适当的转换:
printf(" %-10s %016llx\n", y, (uint64_t)x);
// ^ uint64_t most likely is unsigned long long
// but on 64-bit linux, just unsigned long!!!
转换到uintptr_t
这次没有必要,因为任何指针都会适合 - 并且在将来的某个时候,当第一个 128 位系统出现时,您甚至可能希望重新出现警告(如果确实没有,请再次添加中间强制转换) )。 编辑:如前所述,不修复警告将导致未定义的行为。因此,为了安全起见,您宁愿通过 static_assert(sizeof(uintptr_t) <= sizeof(uint64_t))
明确地发现问题,这将强制调整(谢谢 chux 的提示)。
嗯,正确的格式说明符...幸运的是,有合适的 macros已定义,尽管用法不太好:
printf(" %-10s %016" PRIx64 "\n", y, (uint64_t)(uintptr_t)x);
(在初始示例中为 PRIx32
)。
关于c++ - 警告 : cast from pointer to integer of different size [-Wxpointer-to-int-cast],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56700086/