GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的。它的目标是创建一套完全自由的操作系统,它在编写Linux的时候自己制作了一个标准成为GNU C标准,但是作为GNU C一大特色的__attribute__机制却为许多人所不知,现在让我们一起走进__attribute__的世界,来揭开它的神秘面纱。
对于GNU C的__attribute__机制,它有什么神奇的作用呢?你们是不是已经迫不及待了,对于__attribute__它可以修饰变量属性和函数属性,它的语法格式为:“__attribute__((参数));”,下面我们慢慢道来。
当我们初次学习一门语言的时候,都会写一个很经典的程序,没错就是在屏幕上输出Hello world,现在对我们来说写一段hello world程序,都是顺手捏来的事了,那么你看过这样的Hello world吗?
#include
#include
__attribute__((constructor())) void pre_proc_1(void)
{
printf("\nhello world\n");
}
__attribute__((destructor())) void end_proc_1(void)
{
printf("\nHello World\n",__LINE__);
}
int main(int args,char **argv)
{
return 0;
}
可以猜到程序输出什么结果吗?没错也是输出Hello world,直到为什么这样吗?细心的人肯定看到了在两个子函数前面使用了__attribute__((constructor()))和__attribute__((destructor))来修饰子函数,那么它们的作用是什么意思呢?被__attribute__((constructor()))修饰的函数在主函数前执行,__attribute__((destructor()))修饰的函数在主函数后执行,我们还可以在__attribute__((constructor(101)))在数字,括号中的数字代表函数的优先级,这样我们就可以安排我们函数执行的顺序了,一般0-100为系统使用,我们可以使用100以后的数字,在VC下也有这个属性但是不能添加数字作为优先级,但是我们可以安排我们函数的声明顺序来实现函数的执行顺序。
经过一个简单有意思的程序,下面我们继续来说__attribute__机制,在前面说道__attribute__可以修饰变量和函数属性,下面总结了如何使用__attribute__来修饰变量和函数,让我们一起来感受它的神奇。
函数属性(1)__attribute__((format(archtype,string-index,first-to-check)));
format属性告诉表达式按照printf,scanf,strftime,strfmom参数表格式规则对该函数的参数进行检查。
例:
__attribute__((format(printf,m,n)));
__attribute__((format(scanf,m,n)));
m:第几个参数为格式化字符
n;在参数集合中排在第几
(2)__attribute__((noreturn));
该属性通知编译器从不返回值,当遇到类似函数需要返回值却不可能运行到返回值就已经退出的情况该属性可以避免出现错误信息,例如C语言中的abort()和exit()函数就使用到了该属性。
(3)__attribute__((const));
该属性只能用于带有数值类型参数的函数上,当反复调用带有数值参数的函数时,由于返回值是相同的,所以编译器可以进行优化处理,除第一次需要运算外,其他只需返回第一次运行的结果,进而再快了执行效率。
(4)Noinline & always_line
Nolinline为不内联,always_line为总是内联,我们在使用inline什么内联函数时,函数能否成为内联函数,还要看编译器的具体操作,使用noinline和always_line可以告诉编译器是否执行内联。
(5)看了前面的常用属性,你们可能会问到可以在同一个函数中使用多个参数吗?回答是肯定,并且这在实际中也是非常有用的。
变量属性(1)__attribute__((aligned(n)));
例:
int a __attribute__((aligned(16))) = 0;
变量a将以16位对齐,我们也可以不加数字,如__attribute__((aligned));这样编译器会根据目标机器的情况实现对齐。它不仅可以修饰单个变量,也可以修饰符合变量如结构体,联合等,在实际中会用于修饰结构体,是结构体中的成员按一定的方式字节对齐。
(2)__attribute__((packed));
例:
int a[10] __attribute__((packed));
前面说了字节对齐属性,有的编译会默认使用一种字节对齐方式,假如我们不想使用字节对齐该怎么做呢?该属性就起到了这个作用,使用packed可以取消字节对齐方式。
(3)__attribute__((at(address));
例:
int a __attribute__((at(0x00));
在一些特殊的情况,我们需要将某个变量存放特定的位置时,该属性就起到了作用,该属性的作用就是将变量a存储到绝对地址为0x00的位置处。
(4)__attribute__((section(“section_name”)));
例如:
int a(void) __attribute__((seciton(abc));
说了前面的at属性,现在我们来说seciton属性,他和at有些相同,他的作用是将作用的函数或指定的数据放入指定名为Section_name的段中,一般在汇编文件中我们会使用到。
(5)__attribute__((cleanup(函数名)))
该属性来修饰一个变量,当变量的作用域结束时,调用一个指定的函数。
例如:
void print()(printf(“\nend\n”);
void text()
{
Int a __attribute__((cleanup(print))) = 10;
}
看了这么多属性的作用,大家是否感觉到了GNU编译器的神奇呢?对于__attribute__关键字,大家是否有了更进一步的认识呢?
-
Linux
+关注
关注
87文章
11204浏览量
208701 -
操作系统
+关注
关注
37文章
6676浏览量
123131 -
编译器
+关注
关注
1文章
1617浏览量
49014
原文标题:__attribute__ 你不知道的秘密
文章出处:【微信号:Zlgmcu7890,微信公众号:周立功单片机】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论