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