将函数指针转换为 uintptr_t / intptr_t 无效吗?

Pav*_*kin 6 c type-conversion visual-c++ language-lawyer c11

Microsoft 对 C 和 C++ 的扩展

要执行相同的转换并保持 ANSI 兼容性,您可以在将函数指针转换uintptr_t为数据指针之前将其转换为 a:

int ( * pfunc ) ();
int *pdata;
pdata = ( int * ) (uintptr_t) pfunc;
Run Code Online (Sandbox Code Playgroud)

C 的基本原理,修订版 5.10,2003 年 4 月:

即使使用显式强制转换,将函数指针转换为对象指针或 void 指针也是无效的,反之亦然

C11:

7.20.1.4 能够保存对象指针的整数类型

是否意味着pdata = ( int * ) (uintptr_t) pfunc;无效?

正如史蒂夫·萨米特所说

C 标准的编写假设指向不同对象类型的指针,尤其是指向函数而不是对象类型的指针,可能具有不同的表示形式

虽然pdata = ( int * ) pfunc;会导致UB,但似乎会pdata = ( int * ) (uintptr_t) pfunc;导致IB。这是因为“任何指针类型都可以转换为整数类型”和“整数可以转换为任何指针类型”并且uintptr_t是整数类型。

chu*_*ica 3

\n

是将函数指针转换为uintptr_t / intptr_t

\n
\n

不,这可能是有效的。这可能是未定义的行为

\n
\n

\xc3\xacnt*未定义函数指针的转换。也不指向任何 对象指针。也不至于void *
\npdata = ( int * ) pfunc;未定义的行为

\n

函数指针到整数类型的转换允许

\n
\n

任何指针类型都可以转换为整数类型。除非前面指定,否则结果是实现定义的。如果结果不能以整数类型表示,则行为未定义。结果不必在任何整数类型的值范围内。C17dr 6.3.2.3 6

\n
\n

也允许将整数转换为指针类型。

\n
\n

整数可以转换为任何指针类型。除非前面指定,否则结果是实现定义的,可能未正确对齐,可能不指向引用类型的实体,并且可能是陷阱表示。C17dr 6.3.2.3 6

\n
\n

void *to 整数 tovoid *被定义。 定义了指向/来自的对象指针。void*那么可选 (u)intptr_t类型足以实现往返成功。然而我们关心的是函数指针。通常足够多的函数指针比int *.

\n

因此,将函数指针转换为int *仅通过整数类型才有意义,越宽越好。

\n

VS 可以通过可选类型推荐,并且如果信息在其他平台上无损的话uintptr_t可能就足够了。然而,可能会损失更少的信息,特别是在函数指针指向整数的步骤中,所以我迂腐地建议:uintmax_t

\n
pdata = ( int * ) (uintmax_t) pfunc;\n
Run Code Online (Sandbox Code Playgroud)\n

无论采取什么步骤,代码都可能成为特定于实现的代码,并且值得保护。

\n
#ifdef this && that\n  pdata = ( int * ) (uintmax_t) pfunc;\n#else\n  #error TBD code\n#endif\n
Run Code Online (Sandbox Code Playgroud)\n