gcc扩展

发布时间:2009/05/01      类别:linux编程 | 所属专题:

版权所有,转载请注明:本文出自学与思编程网

GCC对ANSI C进行了很多有用的扩展比如增加了内联(inline)函数,从c++中借鉴了//注释界定符等等。虽然这些扩展有时候很有用,但我们需要明白的是在享受这些扩展的同时,也必须忍受这些扩展带来的移植性烦恼。

扩展1,inline函数

gcc允许我们在源代码中用inline关键字定义一个短小精干的函数,在编译时gcc遇到这些inline函数就用它自己的规则判断该函数是否应该作为一个inline函数,如果可以,就把所有调用该函数的地方像宏一样展开,而不是像其它普通函数那样通过CALL来调用该函数,这样可以减小函数调用的开销,进而提高程序的运行效率。要注意的是稍微复杂一点的函数即使您使用了关键字inline,gcc也不会把它当成一个inline函数来处理。那么什么样的程序一般可以被gcc接受作为inline函数呢?一般的规则是短小且没有复杂的条件控制语句的非递归函数都可以被接受。所以当我们有个符合 inline规则的且被大量调用的函数,就可以考虑把它定义成inline函数,如:

inline int max(int a, int b)
{

return a >= b ? a : b;

}

我们同样也可以用宏来实现上面的功能,如#define MAX(a, b) (a) >= (b) ? (a) : (b) ,但编译器在编译inline函数时会进行类型检查,而宏不会,所以使用inline函数要比使用宏安全。最后,如果多个c源文件中需要使用同一个 inline函数,则最好把它定义在头文件中。Inline函数是在编译的时候(前文中编译过程的第二步)在函数调用处展开的,这就要求在第二步处理时就应该找到该函数的定义(只有申明是不够的),如果我们把它定义在头文件中,我们只需简单的#include该头文件即可,但如果把inline函数定义在另一个.c文件中,编译器就会因第二步无法找到该函数的定义而报错,对于这点我们是有办法解决的,那就是哪个.c文件想用该函数,就在这个.c文件中定义一次,这样做编译时确实不会报错了,如果这个函数也确实被gcc接受为inline函数,这么做是没有任何问题的,但如果不接受其为inline函数则会造成同一程序中多次出现一模一样的代码片段,增加了代码的大小。而普通函数的调用是在连接(前文中编译过程的第四步)时确定其地址的,所以不需要在编译时就知道这个函数定义在哪里,只需看到其申明,了解其参数个数,各个参数类型和返回值类型就可以在第二步中进行语法检查了。

扩展二,c源代码文件名,函数名和代码行号

为了简化调试工作,gcc把c源代码的文件名,函数名当作字符串常量,可以分别通过__FILE__和__FUNC__引用,就像我们自己定义的宏一样使用,gcc还用__LINE__来引用它所在行的行号。如:

printf(”File:%s, Line:%d, Function:%sn”,

__FILE__, __LINE__, __FUNC__);

扩展三,变量属性__attribute__

__attribute__可以用来修饰变量,如char c __attribute__(aligned 4)则是告诉gcc按4字节边界对齐为c分配内存地址,如struct mystruct {char a, int b}__attribute__(packed);则告诉gcc在为mystruct类型的结构体分配内存时不要对齐,只分配最小的空间,在x86平台上如果没有后面的属性,gcc多半会给这个结构体分配8个字节,但有这个属性则只会分配5个字节。__attribute__还有很多属性,我们这里就不一一介绍了,有兴趣的话请参考gcc manual。

扩展四,注释界定符//

GCC在编译程序时认识这个//注释符号了,很方便吧。

还有一些不常用的扩展,本文就不介绍了,如有兴趣可参考gcc manual.

 

版权所有,转载请注明:本文出自学与思编程网

发表评论