can(u)intmax_t是否包含函数指针?

时间:2016-03-28 16:41:18

标签: c

uintmax_t保证大是否需要保存函数指针?

我知道:

  

以下类型指定能够使用的无符号整数类型   表示任何无符号整数类型的任何值:

uintmax_t

  

以下类型指定带有的无符号整数类型   可以将任何有效指向void的指针转换为此类型的属性,   然后转换回指向void的指针,结果将进行比较   等于原始指针:uintptr_t

并且一个void-Pointer可能不大,只能保存一个函数指针,因此uintptr_t也可能不足以容纳一个函数指针。

3 个答案:

答案 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