【问题标题】:Function pointer to __attribute__((const)) function?指向 __attribute__((const)) 函数的函数指针?
【发布时间】:2012-03-15 12:34:04
【问题描述】:

如何(在 GCC/“GNU C”中)声明一个指向 __attribute__((const)) 函数的函数指针?我的想法是,当编译器可以缓存上一次调用的返回值时,我希望编译器避免对通过函数指针调用的函数产生多次调用。

【问题讨论】:

  • 从来没有这样做过,几乎睡着了去研究,但是尝试使用具有 const 属性并接受该指针作为参数的显式声明的函数的地址来包装调用。如果 gcc 可以确定指针地址本身和参数没有改变 - 它应该消除不必要的调用。
  • @Vlad:我也想过,但是 gcc 在我想要的情况下拒绝内联函数。最初我有一个这样的包装函数,但我删除了它以修复内联行为。如果有趣的话,有问题的函数是((pthread_t (*)(void))0xffff0fe0)(Linux-ARM get-thread-pointer 函数)。
  • 有趣的问题。贾斯汀的回答有没有达到预期的效果?
  • @Praxeolitic:是的。

标签: c gcc types function-pointers


【解决方案1】:
typedef void (*t_const_function)(void) __attribute__((const));

static __attribute__((const)) void A(void) {
}

static void B(void) {
}

int main(int argc, const char* argv[]) {
    t_const_function a = A;

    // warning: initialization makes qualified
    // function pointer from unqualified:
    t_const_function b = B;

    return 0;
}

或者只是:

__attribute__((const)) void(*a)(void) = A;

【讨论】:

  • Bleh,当你有一个讨厌的函数指针类型时,typedef 总是解决方案。公认。但是,如果没有typedef,是否有办法在我对主要问题的评论中编写演员表?
  • @R.不幸的是,我确实知道如何在没有typedef 的情况下将其全部转换为一个语句——这在 GCC 4.2 上似乎是不可能的。 ((__attribute__((const)) pthread_t(*)(void))0xffff0fe0) 是我认为的完成方式,但它的解释与您想要的不同(似乎 GCC 将属性应用于返回类型,而不是函数)。
【解决方案2】:

虽然这不是您问题的完全答案,但您可能想知道这一点:

在一般情况下,您不能期望编译器在此处执行您期望的优化。在一般情况下,编译器无法进行必要的别名分析,以了解函数指针的多次使用对应于同一个函数。

在通过指针两次调用函数之间的函数调用,在一般情况下,可能会改变指针内容,从而导致调用的函数在第二次调用中不同。

由于 C 的性质,进行适当的别名分析通常是棘手的,因此这种优化不太可能发生。

【讨论】:

  • 这就是 __attribute__((const)) 的作用——它告诉编译器你知道得更多,并为某些优化开绿灯。
  • 在我的例子中它可以知道,因为指针是一个地址文字(一个整数转换为函数指针)。见 cmets。
  • @Vlad:我认为 Perry 的观点是,即使指向的函数是 const,编译器也必须确保 指针 没有改变调用之间。但这并不难确定,就我而言,这是不可能的,因为它是一个字面绝对地址。
  • 编译器可以处理声明函数属性 const 没问题。问题是当您开始通过函数指针进行间接寻址时。函数的文字名称实际上是一个常量指针,编译器可以知道它没有被改变——但是一个包含指向属性 const 函数的指针的变量是不同的。
  • 如果你知道指向 func 的指针永远不会改变,最简单的方法可能是像你说的那样声明它register,但也要声明指针本身 const 合格。
猜你喜欢
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 2014-10-18
  • 1970-01-01
  • 2016-02-26
  • 1970-01-01
  • 2020-08-12
  • 1970-01-01
相关资源
最近更新 更多