什么是函数属性声明?
在 GNU C 和 C++ 中,您可以使用函数属性来指定某些函数属性,这些属性可能有助于编译器优化调用或更仔细地检查代码的正确性。例如,您可以使用属性来指定函数从不返回 (noreturn)、仅根据其参数的值返回一个值 (const),或者具有 printf 样式的参数 (format)。
使用函数属性声明时,需要用到关键字 __attribute__ ,它的格式如下:
__attribute__ ((list1, list2, ...., list-n))
其中的list内容,可以在gcc.gnu.org官方网站上找到详细的描述,欢迎各位读者阅读我个人解析的list内容。
在书写时,请遵循以下的语法:
__attribute__((attribute_list)) int add(int a, int b); //OK
int __attribute__((attribute_list)) add(int a, int b); //OK
int add(int a, int b) __attribute__((attribute_list)); //OK
建议将所有的函数属性写到函数声明处,因为有些函数属性是不支持写到函数体处,例如weak属性,写到函数体处时将会引发编译错误。
如果在函数声明同时写出函数体时,注意__attribute__((attribute_list))就不能写到函数参数列表后面了:
__attribute__((attribute_list)) int sub(int a, int b){
return a - b;
} //OK
int __attribute__((attribute_list)) sub(int a, int b){
return a - b;
} //OK
int sub(int a, int b) __attribute__((attribute_list)){
return a - b;
} //wrong
第三种写法在编译时会报错。
注意:在函数声明、函数实现两个地方任意一个地方写__attribute__((attribute_list))起到的作用是相同的,也就是说,代码片段:
__attribute__((attribute_list)) int add(int a, int b);
int add(int a, int b){
return a + b;
}
和以下代码片段起到的作用是相同的:
int add(int a, int b);
__attribute__((attribute_list)) int add(int a, int b){
return a + b;
}
现在请考虑一种情况,如果我在函数声明和定义处都加入了函数属性定义__attribute__((attribute_list)) 会发生什么?
现在,我们拿函数属性constructor和destructor做实验,在fun函数的声明处加入constructor声明,在fun函数的实现处加入destructor声明。
注:简单来说,constructor属性用于在程序启动前执行一次函数,destructor属性用于在程序结束时执行一次函数。
#include <stdio.h>
__attribute__((constructor)) void fun(void);
__attribute__((destructor)) void fun(void){
printf("hello world\n");
return;
}
int main(){
printf("into main function\n");
fun();
printf("return from main function\n");
return 0;
}
运行结果为
hello world
into main function
hello world
return from main function
hello world
可以看到,在main函数执行前后fun函数都被执行了,也就是两个属性都起作用了。
同时,如果一个函数有多个声明,多个声明中的函数属性也会叠加。
#include <stdio.h>
__attribute__((constructor)) void fun(void);
__attribute__((destructor)) void fun(void);
void fun(void){
printf("hello world\n");
return;
}
int main(){
printf("into main function\n");
fun();
printf("return from main function\n");
return 0;
}
运行结果和上方代码一致。
如果函数声明在实现后,该函数声明中的函数属性也会附加到函数上去。
#include <stdio.h>
void fun(void){
printf("hello world\n");
return;
}
__attribute__((constructor)) void fun(void);
__attribute__((destructor)) void fun(void);
int main(){
printf("into main function\n");
fun();
printf("return from main function\n");
return 0;
}
运行结果和上方代码一致。
constructor属性和destructor属性并不冲突,但如果是两个相互冲突的属性呢?还请读者自行尝试。