__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
网友评论