【发布时间】:2019-08-13 17:13:39
【问题描述】:
TL;DR:
我需要在我的代码中执行以下操作(非常简化的示例):
int ret = 42;
void * marshaled_ret = (void *) ret;
int unmarshaled_ret = (int) marshaled_ret;
这会导致编译器警告:
警告:从不同大小的整数转换为指针 [-Wint-to-pointer-cast]
我如何才能针对这种特殊情况抑制编译器警告?
背景:我正在围绕特定于平台的多线程库编写一个抽象层。
一个很大的挑战是库期望线程的主函数有不同的签名。 POSIX 有
(void *)(*thread_main)(void *)
而 Windows(实际上)有
int (*thread_main)(void *)
即只有返回类型不同。
因为我需要为所有平台创建一个函数签名,所以我选择了int 作为最受限制的返回类型。在创建线程时,我将用户提供的函数及其参数编组为 struct 并调用包装函数(具有平台预期的签名),然后调用实际的 main 函数。
然而,在 POSIX 上,这涉及将 int 转换为 void * 并返回,如上所示,这会导致编译器警告。
显然,如果您将int 用作指针,则以这种方式将int 转换为指针是一个坏主意(几乎可以保证段错误)。然而,在这种情况下,指针类型只是我的“整数骡子”,从不打算用作指针。
我如何才能针对这种特殊情况抑制编译器警告?
【问题讨论】:
-
使用
uintptr_t作为中间演员。但是,如果您的int超出其界限,您将遇到麻烦。 -
"即只有返回类型不同。" - 指针和
int之间的返回类型和字节数也可能不同。 (x64 8字节指针,4字节int) -
使
ret成为空指针?void *ret = (void *)42; void * marshaled_ret = ret; -
这是最干净的选择,但看在上帝的份上,永远不要尝试并实际使用
ret作为指针,因为地址 42 将在系统保护内存范围... -
@KonradRudolph 看起来你误解了我想要达到的目标。转换为
int→void *→int,语义上它只是一个任意数字,而不是地址。除非int比该特定平台上的指针长,否则截断不是问题。
标签: c casting suppress-warnings