1. GCC应用
GNU C 的一大特色就是__attribute__ 机制。attribute 可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。
attribute 书写特征是:attribute 前后都有两个下划线,并切后面会紧跟一对原括弧,括弧里面是相应的__attribute__ 参数。
attribute 语法格式为:__attribute__ ((attribute-list))
其位置约束为:放于声明的尾部;
之前。
1.1 函数属性举例
使用warn_unused_result :表示需要使用函数的返回值,否则会产生一个警告。
- (BOOL)testFunc:(NSInteger) num __attribute__ ((warn_unused_result));
- (BOOL)testFunc2:(NSInteger) num ;
[object testFunc:1];//have a warning
[object testFunc2:1];
BOOL result = [object testFunc:1];
NSLog(@"%d",result);
其他函数举例
- noreturn : 表示忽略函数没有返回值的警告,异常退出时使用。
- format : 可以给被声明的函数加上类似printf或者scanf的特征,它可以使编译器检查函数声明和函数实际调用参数之间的格式化字符串是否匹配。该功能十分有用,尤其是处理一些很难发现的bug。
- const : 是编译优化,编译器只调用了函数一次,以后只是直接得到了相同的一个返回值。
1.2 变量属性
还没有找到合适的变量属性举例。
1.3 类型属性
aligned (alignment) : 该属性设定一个指定大小的对齐格式(以字节为单位)
struct AttributeMarkS {
short b[3];
} __attribute__ ((aligned (8)));
struct AttributeMarkS2 {
short b[3];
};
struct AttributeMarkS aa;
struct AttributeMarkS2 bb;
NSLog(@"aa:%ld,bb:%ld",sizeof(aa),sizeof(bb));//aa:8,bb:6
packed : 使用该属性对struct 或者union 类型进行定义,设定其类型的每一个变量的内存约束。aligned 属性使被设置的对象占用更多的空间,相反的,使用packed 可以减小对象占用的空间。
2. LLVM应用
Clang支持__attribute__
,是否支持特定的,可以用__has_attribute
进行检查。如下:
#if __has_attribute(const_test)
NSLog(@"have attribute const_test");
#else
NSLog(@"no attribute const_test");//const_test
#endif
availability
主要作用进行版本可用性声明,如下:
void f(void) __attribute__((availability(macosx,introduced=10.4,deprecated=10.6,obsoleted=10.7)));
- introduced: 声明第一次被引入的版本.
- deprecated: 声明不推荐的版本,即从这个版本开始,这个函数不再推荐使用
- obsoleted: 声明被弃用的版本,即从此版本开始,这个函数被弃用了,但是仍然可用。
- unavailable: 声明不可用.
- message 当碰到警告或者错误的时候弹出的消息提示.
文章中是Swift2.0中关于函数可用性的设置,可以进行类比。
overloadable
作用是进行函数的重载(overloading)。
float __attribute__((overloadable)) tgsin(float x) { return sinf(x); }
double __attribute__((overloadable)) tgsin(double x) { return sin(x); }
long double __attribute__((overloadable)) tgsin(long double x) { return sinl(x); }
float tgsin2(float x) { return sinf(x); }
double tgsin2(double x) { return sin(x); }//error ,conflicting types for 'tgsin2'
3. Objective-C库中的包装
查看Objective-C函数库文件中使用attribute的定义主要在文件 NSObjCRuntime.h 中。文章中曾经介绍的系统NSManagedObject类中,归根结底还是利用了attribute的特性。如下注意 NS_CLASS_AVAILABLE
和 NS_REQUIRES_PROPERTY_DEFINITIONS
:
NS_CLASS_AVAILABLE(10_4,3_0) NS_REQUIRES_PROPERTY_DEFINITIONS
@interface NSManagedObject : NSObject {
@private
int32_t _cd_rc;
uintptr_t _cd_stateFlags;
...
}
#define NS_CLASS_AVAILABLE(_mac, _ios) __attribute__((visibility("default"))) NS_AVAILABLE(_mac, _ios)
#if __has_attribute(objc_requires_property_definitions)
#define NS_REQUIRES_PROPERTY_DEFINITIONS __attribute__((objc_requires_property_definitions))
#else
#define NS_REQUIRES_PROPERTY_DEFINITIONS
#endif
文件中还有好多其他的例子,可以详查。另外,文件CFAvailability.h是属性available的封装也可以进行代码分析。
4. 总结
__attribute__
主要是通过编译预处理的方式来进行编译警告提示和编译优化的工作。了解它,有助于我们更好的进行编码。上面列举的仅仅是部分 attribute-list,还有好多没有列举到,这个工作需要慢慢的进行。
5. 参考文献
http://blog.csdn.net/hello_hwc/article/details/42803645
http://www.cnblogs.com/astwish/p/3460618.html
http://nshipster.com/attribute/