uintmax_t
保证大是否需要保存函数指针?
我知道:
以下类型指定能够使用的无符号整数类型 表示任何无符号整数类型的任何值:
uintmax_t
和
以下类型指定带有的无符号整数类型 可以将任何有效指向void的指针转换为此类型的属性, 然后转换回指向void的指针,结果将进行比较 等于原始指针:uintptr_t
并且一个void-Pointer可能不大,只能保存一个函数指针,因此uintptr_t也可能不足以容纳一个函数指针。
答案 0 :(得分:5)
C标准中没有这样的保证。
首先,不能保证任何指针都可以无损地转换为整数类型(NULL指针除外)。确实uintptr_t
必须能够无损地表示void指针(因此任何onject指针)。但是,无法保证实现具有uintptr_t
,因为它和intptr_t
是可选的(第7.20.1.4节的最后一句)。
其次,函数指针不是对象指针,并且不一定可以将其转换为void指针并返回。因此,即使uintptr_t
确实存在,它也可能不足以容纳函数指针。
在X / Open System Interface(XSI)兼容实现(大多数Posix系统)上,您必须能够在void指针和函数指针之间进行转换,并且uintptr_t必须存在。那么在这种情况下,你确实有保证。 (dlsym
系统接口需要void和函数指针之间的可转换性,该接口在问题7(2008)中从XSI移动到基本Posix。但是,uintptr_t的存在仍然是XSI扩展。)< / p>
答案 1 :(得分:4)
不,不是一般的。 void*
因此[u]intptr_t
只能保证足够宽以容纳对象指针,即指向对象类型的指针。在某些平台上,函数指针可以更宽,并且包含的信息不仅仅是函数的入口点。因此,在这样的平台上,void*
或uintptr_t
没有足够的位来表示所需的所有信息。
在许多平台上,函数指针的宽度与对象指针的宽度相同,甚至可以允许它们从一个转换为另一个。但这是C标准的扩展,您必须检查平台文档。
答案 2 :(得分:1)
uintmax_t保证大到足以容纳函数指针吗?
没有保证的方式以及其他人的回答。
然而,函数指针的大小确实存在,并且它确实具有位模式。如果足够大,uintmax_t
可以保持指针的位模式(可能更多)。可以在编译时评估此大小测试。
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
int foo(int x) {
return x+x;
}
int main(void) {
union {
uintmax_t um;
int (*fp)(int);
} u = {0};
assert(sizeof u.um >= sizeof u.fp); // This assertion may fail
u.fp = foo;
uintmax_t save = u.um;
printf("%ju\n", save);
u.um = save;
printf("%d\n", (*u.fp)(42));
return 0;
}
输出
4198816
84