/* 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
}
3条答案
按热度按时间lmvvr0a81#
或者只是:
yk9xbfzb2#
愚者12.2.1对
__attribute__((pure))
和__attribute__((const))
的处理方式有细微的不同。前者只适用于函数声明,从不适用于类型,而后者实际上既适用于函数声明,也适用于指向函数的指针类型(但不适用于函数类型!)。您实际上可以将属性附加到多个级别的指针间接寻址:
上面的
demo1
函数接受一个参数,其类型为“指向不接受参数且为常量的函数的指针,并返回指向接受整数参数且为常量并返回整数的函数的指针”。以上所有内容都可以回答OP的问题。你可以声明一个指向常量函数的指针(但是不能声明一个指针为 pure 函数):
在函数参数列表中,它可能如下所示:
不幸的是,我发现没有办法在声明之外将
__attribute__((const))
附加到指向函数的指针类型上。特别是,它在强制转换中不起作用:但是,您 * 可以 * 将指向函数的指针转换为
typedef
的指向常量函数的指针类型:如果任何愚者开发人员正在阅读本文,请修复
__attribute__((pure))
,使其具有与__attribute__((const))
相同的适用性。n8ghc7c13#
虽然这不是您问题的答案,但您可能想知道:
在一般情况下,编译器不能执行你所期望的优化,编译器不能进行别名分析,以确定函数指针的多次使用对应于同一个函数。
在一般情况下,通过指针的两次函数调用之间的函数调用可能会更改指针内容,从而导致第二次调用中所调用的函数不同。
由于C语言的特性,进行正确的别名分析通常很难,因此这种优化不太可能发生。