• Using GNU C __attribute__ 阅读笔记


    Using GNU C __attribute__ reading notes

    1. 本文讲述GNU编译器的一个特性-__attribute__,这个宏是一个编译器指令,我们在代码中通过定义这个东西,可以inform编译器我们代码 的一些逻辑,从而在编译器避免一些错误,在运行期提高性能。__attribute__在很多代码中都有应用,非常实用。包括我们在看一些老外写的比较成 熟的代码的时候,都能看到这个东西。

    2. __attribute__ format ,这个东西能告知编译器,我们的代码在处理printf,scanf这样变参数的函数的时候,哪个参数是format string,哪个参数是参数列表,这样可以避免代码中的一些问题,比如:

    Code: Select all
    /* like printf() but to standard error only */
    extern void eprintf(const char *format, ...)
       __attribute__((format(printf, 1, 2)));  /* 1=format 2=params */

    /* printf only if debugging is at the desired level */
    extern void dprintf(int dlevel, const char *format, ...)
       __attribute__((format(printf, 2, 3)));  /* 2=format 3=params */


    从上面可以看出,我们定义了eprintf函数,第一个参数是Format String,第二个参数是对应Format String的参数列表,下面的dprintf也是一样,这样一来,编译器就能检测出下面这样的代码错误:

    Code: Select all
    $ cat test.c
    1  extern void eprintf(const char *format, ...)
    2               __attribute__((format(printf, 1, 2)));
    3
    4  void foo()
    5  {
    6      eprintf("s=%s\n", 5);             /* error on this line */
    7
    8      eprintf("n=%d,%d,%d\n", 1, 2);    /* error on this line */
    9  }

    $ cc -Wall -c test.c
    test.c: In function `foo':
    test.c:6: warning: format argument is not a pointer (arg 2)
    test.c:8: warning: too few arguments for format


    3. __attribute__ noreturn,这是是告诉编译器一个函数是没有return的,我觉得用处不大,自己看附件英文原文吧。

    4. __attribute__ const, 这个东西能告诉编译器,在给定参数的情况下,这个function始终返回同样的值。这样可以帮助程序提高性能,比如:

    Code: Select all
    extern int square(int n) __attribute__((const));
    ...
       for (i = 0; i < 100; i++ )
       {
          total += square(5) + i;
       }


    如 果我们在square函数中没有定义__attribute__ const的话,在下面的那个循环中,程序每次都要产生一个调用square函数的代码。但是这里指定了const之后,程序就知道,对于同一个输入参数 5,返回值都是一样的。这样程序就会执行一次square,然后cache这个函数的return value,这样下次循环开始,对square函数的调用就没有函数调用的逻辑了,直接返回上次的结果。

    5. 混用上面的东西,下面两种写法都可以:

    Code: Select all
    /* send printf-like message to stderr and exit */
    extern void die(const char *format, ...)
       __attribute__((noreturn))
       __attribute__((format(printf, 1, 2)));

    /*or*/

    extern void die(const char *format, ...)
       __attribute__((noreturn, format(printf, 1, 2)));


    6. 使用__attribute__带来的程序可移植性的问题,由于__attribute__是GNU编译器专用的,所以如果我们这样的代码要移植到非GNU的环境下,怎么办呢?很简单,使用条件编译:

    /* If we're not using GNU C, elide __attribute__ */
    #ifndef __GNUC__
    # define __attribute__(x) /*NOTHING*/
    #endif

    这 里define __attribute__(x),看到了吧?__attribute__只接受一个参数,但我们看到在使用format,const这些东西的时候,明 明有好几个参数啊?再仔细看,我们在使用__attribute__的时候,在format,const这些关键字的外面还有一层括号,也就是说,我们在 每个__attribute__的里面,都用了两层括号,包括了format,const这些东西的那层括号就指明了括号中的内容是一个参数,这样就符合 这里的定义了。注:这样的做法在windows平台下也很常见,应该说这是C语言编程,特别是宏编程中一个非常常用的技巧,通过这样的技巧,就可以把一个 不定参数的东西定义成只有一个参数的宏原型。

    7. 一点注意:

    在 使用__attribute__的时候,要注意的是,我们必须在函数的申明处使用__attribute__,在函数的实现处,是不能定义的--也就是 说,对于每个想使用__attribute__特性的函数,必须手动定义一个函数申明,然后是函数实现,光写一个函数实现是不可以的,因为 __attribute__不能被定义在函数实现上(不知道为什么,GNU的C编译器就是这样的),比如:

    Code: Select all
    /* function declaration */
    void die(const char *format, ...) __attribute__((noreturn))
                                      __attribute__((format(printf,1,2)));

    void die(const char *format, ...)
    {
       /* function definition */
    }
  • 相关阅读:
    网络基本功(一)细说网络传输
    关于指针的理解
    百度地图定位,标注以及地图中心点问题
    ios 将彩色照片转化成黑白等几种类型
    在 iOS 应用中直接跳转到 AppStore 的方法
    ios中判断当前手机的网络状态
    NTFS 读写高手进阶 Windows 格式硬盘 Mac存文件 开启 ...(转载)
    tableviewcell 中使用autolayout自适应高度
    ios 3D Touch功能的实现
    一些牛人分享的ios技巧,保留着
  • 原文地址:https://www.cnblogs.com/super119/p/2005592.html
Copyright © 2020-2023  润新知