gcc 函数指针是否指向__attribute__((const))函数?

x8diyxa7  于 2022-12-13  发布在  其他
关注(0)|答案(3)|浏览(168)

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

lmvvr0a8

lmvvr0a81#

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;
yk9xbfzb

yk9xbfzb2#

愚者12.2.1对__attribute__((pure))__attribute__((const))的处理方式有细微的不同。前者只适用于函数声明,从不适用于类型,而后者实际上既适用于函数声明,也适用于指向函数的指针类型(但不适用于函数类型!)。

/* Function declarations */

int const_fn(int) __attribute__((const)); // OK
int pure_fn(int) __attribute__((pure)); // OK

/* Function type definitions */

typedef int const_fn0_t(int) __attribute__((const)); // warning: 'const' attribute ignored
typedef int pure_fn0_t(int) __attribute__((pure)); // warning: 'pure' attribute ignored

typedef int __attribute__((const)) const_fn1_t(int); // warning: 'const' attribute ignored
typedef int __attribute__((pure)) pure_fn1_t(int); // warning: 'pure' attribute ignored

typedef __attribute__((const)) int const_fn2_t(int); // warning: 'const' attribute ignored
typedef __attribute__((pure)) int pure_fn2_t(int); // warning: 'pure' attribute ignored

__attribute__((const)) typedef int const_fn3_t(int); // warning: 'const' attribute ignored
__attribute__((pure)) typedef int pure_fn3_t(int); // warning: 'pure' attribute ignored

/* Pointer-to-function type definitions */

typedef int (*const_fn0_ptr_t)(int) __attribute__((const)); // OK
typedef int (*pure_fn0_ptr_t)(int) __attribute__((pure)); // warning: 'pure' attribute ignored

typedef int (* __attribute__((const)) const_fn1_ptr_t)(int); // OK
typedef int (* __attribute__((pure)) pure_fn1_ptr_t)(int); // warning: 'pure' attribute ignored

typedef int __attribute__((const)) (*const_fn2_ptr_t)(int); // OK
typedef int __attribute__((pure)) (*pure_fn2_ptr_t)(int); // warning: 'pure' attribute ignored

typedef __attribute__((const)) int (*const_fn3_ptr_t)(int); // OK
typedef __attribute__((pure)) int (*pure_fn3_ptr_t)(int); // warning: 'pure' attribute ignored

__attribute__((const)) typedef int (*const_fn4_ptr_t)(int); // OK
__attribute__((pure)) typedef int (*pure_fn4_ptr_t)(int); // warning: 'pure' attribute ignored

void demo(const_fn0_t *pcf0,
          const_fn1_t *pcf1,
          const_fn2_t *pcf2,
          const_fn3_t *pcf3,
          pure_fn0_t *ppf0,
          pure_fn1_t *ppf1,
          pure_fn2_t *ppf2,
          pure_fn3_t *ppf3,
          const_fn0_ptr_t cfp0,
          const_fn1_ptr_t cfp1,
          const_fn2_ptr_t cfp2,
          const_fn3_ptr_t cfp3,
          const_fn4_ptr_t cfp4,
          pure_fn0_ptr_t pfp0,
          pure_fn1_ptr_t pfp1,
          pure_fn2_ptr_t pfp2,
          pure_fn3_ptr_t pfp3,
          pure_fn4_ptr_t pfp4)
{
    /* calling functions directly */
    const_fn(0); // warning: statement with no effect
    pure_fn(0); // warning: statement with no effect

    /* calling through pointers to function types */
    pcf0(0); // no warning
    pcf1(0); // no warning
    pcf2(0); // no warning
    pcf3(0); // no warning
    ppf0(0); // no warning
    ppf1(0); // no warning
    ppf2(0); // no warning
    ppf3(0); // no warning

    /* calling through pointer-to-function types */
    cfp0(0); // warning: statement with no effect
    cfp1(0); // warning: statement with no effect
    cfp2(0); // warning: statement with no effect
    cfp3(0); // warning: statement with no effect
    cfp4(0); // warning: statement with no effect
    pfp0(0); // no warning
    pfp1(0); // no warning
    pfp2(0); // no warning
    pfp3(0); // no warning
    pfp4(0); // no warning
}

您实际上可以将属性附加到多个级别的指针间接寻址:

typedef int (*const_fn_ptr_t)(int) __attribute__((const));

int demo1(const_fn_ptr_t (*pcf)(void) __attribute__((const))) {
    pcf(); // warning: statement with no effect
    pcf()(0); // warning: statement with no effect

    const_fn_ptr_t cfp = pcf(); // no warning
    cfp(0); // warning: statement with no effect
    return cfp(0); // no warning
}

上面的demo1函数接受一个参数,其类型为“指向不接受参数且为常量的函数的指针,并返回指向接受整数参数且为常量并返回整数的函数的指针”。
以上所有内容都可以回答OP的问题。你可以声明一个指向常量函数的指针(但是不能声明一个指针为 pure 函数):

int (*pf)(void *) __attribute__((const));

在函数参数列表中,它可能如下所示:

void sort(void *array[],
          size_t array_size,
          int (*compare)(const void *, const void *) __attribute__((const)))
{
    compare(array[0], array[1]); // warning: statement with no effect
}

不幸的是,我发现没有办法在声明之外将__attribute__((const))附加到指向函数的指针类型上。特别是,它在强制转换中不起作用:

void demo2(int (*pf)(int)) {
    ((int (* __attribute((const)))(int)) pf)(0); // warning: 'const' attribute does not apply to types
}

但是,您 * 可以 * 将指向函数的指针转换为typedef的指向常量函数的指针类型:

void demo3(int (*pf)(int)) {
    pf(0); // no warning
    typedef int (*cfp_t)(int) __attribute__((const));
    ((cfp_t) pf)(0); // warning: statement with no effect
}

如果任何愚者开发人员正在阅读本文,请修复__attribute__((pure)),使其具有与__attribute__((const))相同的适用性。

n8ghc7c1

n8ghc7c13#

虽然这不是您问题的答案,但您可能想知道:
在一般情况下,编译器不能执行你所期望的优化,编译器不能进行别名分析,以确定函数指针的多次使用对应于同一个函数。
在一般情况下,通过指针的两次函数调用之间的函数调用可能会更改指针内容,从而导致第二次调用中所调用的函数不同。
由于C语言的特性,进行正确的别名分析通常很难,因此这种优化不太可能发生。

相关问题