__attribute__

作者: R0b1n_L33 | 来源:发表于2018-04-13 19:13 被阅读10次

    __attribute__是GCC启用的很有用的编译器指令
    类似于ISO C的#pragma
    在LLVM下得到了扩充

    常用的有:

    • __attribute__((const)):用于函数式编程,所修饰的函数只会计算一次,后续调用都返回第一次计算出的返回值
    • __attribute__((overloading)):用于C函数的可重载化
    • __attribute__((availability)):这个大家在OC中应该有所见闻,用来标记所修饰符号适用的系统版本
    • __attribute__((unused)):这个在调试的时候应该会用过,类似于__unused修饰符,假如修饰的符号未被后续程序调用,也不会产生警告
    • __attribute__((nonnull)):类似于OC中的nonnull修饰符和Swift中的"!"修饰符,这个参数存空值会发出警告
    • __attribute__((format, m, n)):用于使用printf,scanf等C语言可变参数函数模型。意味着第m个参数是格式字符串,第n个参数开始是变参
    • __attribute__((cleanup)):类似于Swift中的defer关键字,其修饰的函数会在当前函数作用域退出时执行
    • __attribute__((always_inline)):
      一般情况下,如果不做编译优化的话函数是不会被自动内联的。对于已经声明为内联的函数,这个修饰符让编译器忽略其他限制条件把该函数内联处理。一旦无法执行内联操作,编译器便会报错。但是假如这个函数被间接调用(例如使用函数指针),编译器能不能把它内联就不确定了。这个时候若无法内联,编译器也不一定会报错。
    • __attribute__((noreturn)):这个修饰的函数类似于Swift中的返回值类型为Never的函数。它们没有返回值,往往会一直运行下去或就此退出程序。例如C函数库中的abort(),exit(),还有AFNetworking中也有如下代码
    + (void) __attribute__((noreturn)) networkRequestThreadEntryPoint:(id)__unused object {
        do {
            @autoreleasepool {
                [[NSRunLoop currentRunLoop] run];
            }
        } while (YES);
    }
    

    乃是用于开启一个新的NSThread,内驻一个NSRunLoop循环处理网络请求。

    • __attribute__((weak)):
      这就和OC/Swift中的弱引用类似,避免程序因为引用一个不存在的外部符号(就像extern xxx)而崩溃。同时,当外部有相同的强引用符号将使用外部符号,也就是为外部符号提供了一个override的途径。

    • __attribute__ ((visibility ("visibility_type")))
      visibility属性是在ELF(Executable & Linkable Format,是二进制文件的存储格式和布局,一般是基于GCC的Linux系统使用的格式;Darwin也就是苹果内核使用的是Mach-O格式)中定义的符号可见性,可以以此确定不同域之间是否能够引用指定符号。

    void __attribute__ ((visibility ("protected")))
    f () { /* Do something. */; }
    int i __attribute__ ((visibility ("hidden")));
    

    一般有如下四个visibility_type:

    • default
      默认的visibility,可override别的可能改变符号可见性的attribute选项。一般加入了动态符号表中,可被其他模块看到,可以被相同的符号override。
    • hidden
      hidden修饰的符号不会放进ELF的动态符号表(Dynamic Symbol Table, 用于ELF/Mach-O形式的动态链接库(PSO)声明可被外部引用的符号)中,这样别的module就不能直接引用该符号,但是可以通过函数指针的传递间接引用。
    • internal
      internal和hidden基本是一样的,唯一的区别是它连间接引用都不允许,只能“自给自足”。
    • protected
      protected修饰的符号是可以放入ELF的动态符号表的。但是别的module的符号不能override本module的相同符号。这样引用的首先是本module的符号。

    Reference

    Declaring Attributes of Functions

    相关文章

      网友评论

      本文标题:__attribute__

      本文链接:https://www.haomeiwen.com/subject/myjhkftx.html