zoukankan      html  css  js  c++  java
  • __attribute__关键字

    GCC使用__attribute__关键字来描述函数,变量和数据类型的属性,用于编译器对源代码的优化。

    GCC使用__attribute__关键字来描述函数,变量和数据类型的属性,用于编译器对源代码的优化。

    描述函数属性的几个重要的关键字:

    void noreturnfun() __attribute__((noreturn));//函数不会返回。

    void centon() __attribute__((alias("__centon")));//设置函数别名,函数是__cencon,别名是centon.

    void main_enter() __attribute__((constructor));//main_enter函数在进入main函数前调用

    void main_exit() __attribute__((destructor));//main_exit函数在main函数返回后调用

    void fun() __attribute__ ((noinline));//fun函数不能作为inline函数优化

    void fun() __attribute__ ((section("specials”)));//将函数放到specials段中,而不是通常的text段中

    no_instrument_function、constructor和destructor关键字主要用于剖析(profiling)源代码的。

    在调某个用函数之前和退出某个函数之后调用这些剖析函数,配合addr2line工具可以统计程序的运行状态。__cyg_profile_func_enter和__cyg_profile_func_exit是GCC指定的进入和返回调用的函数名。配合no_instrument_function关键字属性可以使用它记录剖析数据,在编译这样的代码的时候,需要在gcc的命令行中加入-finstrument-functions选项,如果要使用addr2line工具分析源代码,则还要加上-g的gcc命令行选项使得源代码中的符号可以保留。这2个函数需要2个参数,void *func_address是将要调用的函数地址,void *call_site是调用该函数的地址。

    void __cyg_profile_func_enter( void *func_address, void *call_site )
                                    __attribute__ ((no_instrument_function));

    void __cyg_profile_func_exit ( void *func_address, void *call_site )
                                    __attribute__ ((no_instrument_function));

    constructor和destructo是对main函数做上述剖析的关键字,不过这个函数的名称就可以不特定了,而且这样的函数没有参数。如下:

    void __main_enter(void) __attribute__ ((constructor));

    void __main_exit(void) __attribute__ ((destructor));

    描述变量属性的几个重要的关键字:

    int alivalue __attribute__ ((aligned(32)));//变量所存放的内存地址32字节边界对齐

    struct zrecord {
    char id;
    int zar[32] __attribute__ ((packed));
    };//紧凑安排数据结构中的成员元素。如果不使用packed属性则将zar数组按最小的对齐方式在内存中安排空间,X86平台为4,这样在id和zar之间将会有3个字节的空洞存在。而使用了packed属性后,将不会存在这样的空洞。这次属性是依赖与硬件平台的。

    struct domx __attribute__ ((section(“domx”))) = { 0 };
    int trigger __attribute__ ((section(“MONLOG”))) = 0; //不将全局变量放在默认的data或bss段中。而指定特定的段中。

    描述数据类型的几个重要的关键字:

    struct blockm{

          char j[3];

    }__attribute__((aligned(32)));//此数据类型的变量的内存地址32字节边界对齐

    复合声明返回值(Compound Statements Returning a Value):

    在一对圆括号中的最后一个表达式所计算的值为返回值。如:

    int rslt = ({

                        int a=5;

                        a+3;

                 });//rslt所获得的返回值为8

    这个特性的通常用处可书的P87(文档P112)参考。

    函数参数构造(Function Argument Construction):

    GCC内建了3个函数,用于对某一函数的参数构造,调用相关函数,获得相关函数的返回值。

    void *__builtin_apply_args(void);//构造调用此函数的父函数的参数,这些参数都是保存在函数栈(stack)中的。

    void *__builtin_apply(void (*func)(), void *arguments, int size);//调用相关函数,第一参数是相关函数的执政,第二个参数是刚才构造参数的函数的返回的指针,第三个参数是建立一个新的栈(stack)而从旧栈中复制数据的尺寸。

    __builtin_return(void *result);//获得相关函数的返回。参数是刚才调用相关函数的函数的返回指针。

    如:

    #include <stdio.h>
    int passthrough();
    int average();

    int main(int argc,char *argv[])
    {
       int result;
       result = passthrough();
       printf(“result=%d ”,result);
       return (0);
    }
    int passthourgh(int a,int b,int c)
    {
    void *record;
    void *playback;
    void (* fn)() = (void (*) ()) average;
    record = __builtin_apply_args();
    playback = __builtin_apply(fn,record,128);
       __builtin_return(playback);
    }

    int average(int a,int b,int c)
    {
       Return ((a+b+c)/3;
    }

    内联函数(Inline function):

    内联函数在某些情况下类似与宏(macro)。

    在一定条件下编译,内联函数将直接将代码内嵌到调用它的父函数中,编译时指定-O选项才可能被内嵌。也可以指定内嵌函数一个属性“always_inline”强制内嵌。

    有几种情况将不内嵌,而作为普通函数调用:

    1、 不确定数量参数的函数

    2、 调用alloca类库函数的

    3、 有可变尺寸数组声明的。

    4、 非本地goto的。

    5、 嵌套调用的。

    使用ISO C标准的时候,可以使用__inline__关键字代替inline关键字。

    在glib的regex_internal.h文件中有这么几行:
    #ifdef __GNUC__
    # define __attribute __attribute__
    #else
    # define __attribute
    #endif

    原来两个是一会事

    __attribute__((visibility("default")))

    这个关键字与gcc编译参数-fvisibility=hidden配合使用,如果使用了hidden参数,那么该.so库所有符号只对内可见,对外不可见,即使链接了这个.so库,还是不能调用其中的符合(函数等);

    对于大型工程,为了避免同名符号冲突(默认情况下,先链接的.so库符号会被可执行程序先链接,即如果有两个fun函数,分别在a.so 和 b.so,先链接a,则使用a的fun函数),可以先使用-fvisibility=hidden将所有符号隐藏,然后在需要对外的符号前添加__attribute__((visibility("default")))属性来保证符号对外可见。

    当然也可以反过来,将-fvisibility设置为"default"或不设置这个属性,默认所有符号都对外可见,然后在不对外可见的函数或变量前添加__attribute__((visibility("hidden")))来隐藏该符号

     
    这句主要作用是提示编译器,对这个函数的调用需要像printf一样,用对应的format字符串来check可变参数的数据类型。

    例如:
    extern int my_printf (void *my_object, const char *my_format, ...)
    __attribute__ ((format (printf, 2, 3)));

    format (printf, 2, 3)告诉编译器,my_format相当于printf的format,而可变参数是从my_printf的第3个参数开始。

    这样编译器就会在编译时用和printf一样的check法则来确认可变参数是否正确了。
  • 相关阅读:
    我为何需要使用空接口?
    Castle 整合.NET Remoting
    MVC结构简介
    在asp.net页面上得到Castle容器的实例
    Castle.MVC框架介绍
    08.vue-router动态路由匹配
    07. vue-router嵌套路由
    06.路由重定向
    04 Vue Router路由管理器
    ES6新特性之 let 、const
  • 原文地址:https://www.cnblogs.com/klb561/p/14115054.html
Copyright © 2011-2022 走看看