首页 文章

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

提问于
浏览
4

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

我知道这个:

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

以下类型指定一个无符号整数类型,其属性是任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,结果将比较原始指针:uintptr_t

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

3 回答

  • 5

    不,不是一般的 . void* 因此 [u]intptr_t 仅保证足够宽以容纳对象指针,即指向对象类型的指针 . 在某些平台上,函数指针可以更宽,并且包含的信息不仅仅是函数的入口点 . 因此,在这样的平台上, void*uintptr_t 没有足够的位来表示所需的所有信息 .

    在许多平台上,函数指针的宽度与对象指针的宽度相同,甚至可以允许它们从一个转换为另一个 . 但这是C标准的扩展,您必须检查平台文档 .

  • 1

    C标准中没有这样的保证 .

    首先,不能保证任何指针都可以无损地转换为整数类型(NULL指针除外) . 确实 uintptr_t 必须能够无损地表示空指针(因此任何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扩展 . )

  • 4

    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
    

相关问题