警告:从指针强制转换为不同大小的整数[-Wxpointer-to-int-cast]

时间:2019-06-21 08:58:09

标签: c++ c

尝试编译代码时出现警告。我知道它与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)

2 个答案:

答案 0 :(得分:2)

好吧,在您的系统上,指针显然是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个半字节)。如果要在 any 系统上拥有所有八个字节(用于统一日志),则可以再次进行适当的强制转换:

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))明确地抓住问题,该问题将强制进行调整(感谢提示,谢谢)。

好吧,正确的格式说明符...幸运的是,虽然用法不是很好,但已经定义了适当的macros

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

(在最初的示例中为PRIx32

答案 1 :(得分:1)

uint32_t = 32位。

您的指针= 64位。

发出警告。您可以使用%p打印指针,或者,如果需要整数,则强制转换为size_t并使用z修饰符(SO here)。