__attribute__是GNU C特色之一,在iOS用的比較廣泛宠互。如果你沒有用過畏线,那系統(tǒng)庫你總用過,在Foundation.framework中有很多地方用到__attribute__特性良价。__attribute__ 可以設置函數(shù)屬性(Function Attribute )寝殴、變量屬性(Variable Attribute )和類型屬性(Type Attribute )蒿叠。接下來就從iOS中常見用法談起。
1. format
作用:編譯器會檢查格式化字符串與“...”的匹配情況蚣常,防止產(chǎn)生難以發(fā)現(xiàn)的Bug市咽。
用法:
__attribute__((format(printf,m,n)))
__attribute__((format(scanf,m,n)))
其中參數(shù)m與n的含義為:
m 格式化字符串(format string)的位置(順序從1開始);
n 參數(shù)“…”的位置(順序從1開始)抵蚊;
例子:
FOUNDATION_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
#define NS_FORMAT_FUNCTION(F,A) __attribute__((format(__NSString__, F, A)))
#define kMaxStringLen 512
extern void MyLog(const char *tag,const char *format,...) __attribute__((format(printf,2,3)));
void MyLog(const char *tag,const char *format,...) {
va_list ap;
va_start(ap, format);
char* pBuf = (char*)malloc(kMaxStringLen);
if (pBuf != NULL)
{
vsnprintf(pBuf, kMaxStringLen, format, ap);
}
va_end(ap);
printf("TAG:%s Message:%s",tag,pBuf);
free(pBuf);
}
2. deprecated
作用:使編譯會給出過時的警告施绎。
用法:
__attribute__((deprecated))
__attribute__((deprecated(s)))
例子:
#define DEPRECATED_ATTRIBUTE __attribute__((deprecated))
#if __has_feature(attribute_deprecated_with_message)
#define DEPRECATED_MSG_ATTRIBUTE(s) __attribute__((deprecated(s)))
#else
#define DEPRECATED_MSG_ATTRIBUTE(s) __attribute__((deprecated))
#endif
3. availability
作用:指明API版本的變更。
用法:
__attribute__((availability(macosx,introduced=m,deprecated=n)))
m 引入的版本
n 過時的版本
例子:
#define CF_DEPRECATED_IOS(_iosIntro, _iosDep, ...) __attribute__((availability(ios,introduced=_iosIntro,deprecated=_iosDep,message="" __VA_ARGS__)))
4. unavailable
作用:告訴編譯器該方法不可用贞绳,如果強行調(diào)用編譯器會提示錯誤谷醉。比如某個類在構造的時候不想直接通過init來初始化,只能通過特定的初始化方法冈闭,就可以將init方法標記為unavailable俱尼。
用法:
__attribute__((unavailable))
例子:
#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
#define NS_UNAVAILABLE UNAVAILABLE_ATTRIBUTE
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property(nonatomic,copy) NSString *name;
@property(nonatomic,assign) NSUInteger age;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithName:(NSString *)name age:(NSUInteger)age;
@end
5. const
作用:用于帶有數(shù)值類型參數(shù)的函數(shù)上。當重復調(diào)用帶有數(shù)值參數(shù)的函數(shù)時萎攒,由于返回值是相同的遇八,所以此時編譯器可以進行優(yōu)化處理,除第一次需要運算外耍休, 其它只需要返回第一次的結(jié)果就可以了刃永,進而可以提高效率。該屬性主要適用于沒有靜態(tài)狀態(tài)和副作用的一些函數(shù)羊精,并且返回值僅僅依賴輸入的參數(shù)斯够。(const參數(shù)不能用在帶有指針類型參數(shù)的函數(shù)中,因為該屬性不但影響函數(shù)的參數(shù)值园匹,同樣也影響到了參數(shù)指向的數(shù)據(jù)雳刺,它可能會對代碼本身產(chǎn)生嚴重甚至是不可恢復的嚴重后果。)
用法:
__attribute__((const))
例子:
int __attribute__((const)) add(int x)
{
printf("%s(%d)\n", __FUNCTION__, x);
return x + 1;
}
int add2(int x)
{
printf("%s(%d)\n", __FUNCTION__, x);
return x + 1;
}
int main(int argc, char* argv[])
{
int i, j;
i = add(10);
j = add(10);
printf("%d %d\n", i, j);
i = add2(10);
j = add2(10);
printf("%d %d\n", i, j);
return 0;
}
6. cleanup
作用:離開作用域之后執(zhí)行指定的方法裸违。實際應用中可以在作用域結(jié)束之后做一些特定的工作掖桦,比如清理。
用法 :__attribute__((cleanup(...)))
例子:
static void stringCleanUp(__strong NSString **string) {
NSLog(@"%@", *string);
}
void testCleanUp() {
__strong NSString *string __attribute__((cleanup(stringCleanUp))) = @"stringCleanUp";
}
static void blockCleanUp(__strong void(^ *block)()) {
if (*block) {
(*block)();
}
}
void testBlockCleanUp() {
__strong void(^block)() __attribute__((cleanup(blockCleanUp))) = ^{
NSLog(@"block");
};
}
static void lambdaCleanUp(void (**lambda)()) {
if (*lambda) {
(*lambda)();
}
}
void testLambdaCleanUp() {
void (*lambda)() __attribute__((cleanup(lambdaCleanUp))) = []() {
puts("lambda");
};
}
int main(int argc, char * argv[]) {
@autoreleasepool {
testCleanUp();
testBlockCleanUp();
testLambdaCleanUp();
}
return 0;
}
//結(jié)合宏定義使用
#define BlockCleanUp __strong void(^block)() __attribute__((cleanup(blockCleanUp))) = ^
#define LambdaCleanUp void (*lambda)() __attribute__((cleanup(lambdaCleanUp))) = []()
void testDefine() {
BlockCleanUp {
puts("BlockCleanUp");
};
LambdaCleanUp{
puts("LambdaCleanUp");
};
}
7. constructor與destructor
作用:__attribute__((constructor)) 在main函數(shù)之前執(zhí)行,__attribute__((destructor)) 在main函數(shù)之后執(zhí)行供汛。__attribute__((constructor(PRIORITY)))和__attribute__((destructor(PRIORITY)))按優(yōu)先級執(zhí)行枪汪。(可用于動態(tài)庫注入的Hook)
用法:
__attribute__((constructor))
__attribute__((destructor))
__attribute__((constructor(PRIORITY)))
__attribute__((destructor(PRIORITY)))
PRIORITY 為優(yōu)先級
例子:
void __attribute__((constructor)) start() {
NSLog(@"%s",__FUNCTION__);
}
void __attribute__((destructor)) end() {
NSLog(@"%s",__FUNCTION__);
}
![Uploading E71D5B89-60DF-47C6-A923-F731680F25B6_088963.png . . .]int main(int argc, char * argv[]) {
NSLog(@"%s",__FUNCTION__);
return 0;
}
void __attribute__((constructor)) start() {
NSLog(@"%s",__FUNCTION__);
}
void __attribute__((constructor(100))) start100() {
NSLog(@"%s",__FUNCTION__);
}
void __attribute__((constructor(101))) start101() {
NSLog(@"%s",__FUNCTION__);
}
void __attribute__((destructor)) end() {
NSLog(@"%s",__FUNCTION__);
}
void __attribute__((destructor)) end100() {
NSLog(@"%s",__FUNCTION__);
}
void __attribute__((destructor)) end101() {
NSLog(@"%s",__FUNCTION__);
}
int main(int argc, char * argv[]) {
NSLog(@"%s",__FUNCTION__);
return 0;
}
8. noreturn
作用:定義有返回值的函數(shù)時扶欣,而實際情況有可能沒有返回值艰毒,此時編譯器會報錯晋修。加上attribute((noreturn))則可以很好的處理類似這種問題伴奥。
用法:
__attribute__((noreturn))
例子:
void __attribute__((noreturn)) onExit();
int test(int state) {
if (state == 1) {
onExit();
}else {
return 0;
}
}
9. nonnull
作用:編譯器對函數(shù)參數(shù)進行NULL的檢查
用法:__attribute__((nonnull(...)))
extern void *my_memcpy_2 (void *dest, const void *src, size_t len) __attribute__((nonnull (1, 2)));
extern void *my_memcpy_3 (void *dest, const void *src, const void *other, size_t len) __attribute__((nonnull (1, 2, 3)));
void test_my_memcpy() {
my_memcpy_2(NULL, NULL, 0);
my_memcpy_3("", "", NULL, 0);
}
10. aligned 與 packed
作用:aligned(m) 將強制編譯器盡其所能地確保變量在分配空間時采用m字節(jié)對齊方式惜论。packed該屬性對struct 或者union 類型進行定義凯旭,設定其類型的每一個變量的內(nèi)存約束惫霸,當用在enum 類型定義時封恰,暗示了應該使用最小完整的類型矮烹。aligned 屬性使被設置的對象占用更多的空間越庇,使用packed 可以減小對象占用的空間罩锐。
用法:
attribute ((aligned (m)))
attribute ((aligned))
attribute ((packed))
例子:
//運行在iPhone5模擬器上
struct p {
int a;
char b;
short c;
}__attribute__((aligned(4))) pp;
struct m {
char a;
int b;
short c;
}__attribute__((aligned(4))) mm;
struct o {
int a;
char b;
short c;
}oo;
struct x {
int a;
char b;
struct p px;
short c;
}__attribute__((aligned(8))) xx;
struct MyStruct {
char c;
int i;
short s;
}__attribute__ ((__packed__));
struct MyStruct1 {
char c;
int i;
short s;
}__attribute__ ((aligned));
struct MyStruct2 {
char c;
int i;
short s;
}__attribute__ ((aligned(4)));
struct MyStruct3 {
char c;
int i;
short s;
}__attribute__ ((aligned(8)));
struct MyStruct4 {
char c;
int i;
short s;
}__attribute__ ((aligned(16)));
int main(int argc, char * argv[]) {
printf("sizeof(int)=%lu,sizeof(short)=%lu.sizeof(char)=%lu\n",sizeof(int),sizeof(short),sizeof(char));
printf("pp=%lu,mm=%lu \n", sizeof(pp),sizeof(mm));
printf("oo=%lu,xx=%lu \n", sizeof(oo),sizeof(xx));
printf("mystruct=%lu \n", sizeof(struct MyStruct));
printf("mystruct1=%lu \n", sizeof(struct MyStruct1));
printf("mystruct2=%lu \n", sizeof(struct MyStruct2));
printf("mystruct3=%lu \n", sizeof(struct MyStruct3));
printf("mystruct4=%lu \n", sizeof(struct MyStruct4));
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
參考資料:
http://nshipster.com/attribute/