一套完全自由的操作系统都有这个秘密

电子说

1.2w人已加入

描述

GNU计划,又称革奴计划,是由Richard Stallman1983927日公开发起的。它的目标是创建一套完全自由的操作系统,它在编写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__关键字,大家是否有了更进一步的认识呢?

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分