一、宏
宏的常見用法:
1、常見字符串抽成宏
2、常見代碼抽成宏
#define DEFINE @"Hello"
#define WIDTH 10.0
#define ZYXUserInstance [ZYXUser shareInstance]
二、const 常量
翻譯 const :常數(shù),不變的。
const是一個關(guān)鍵字。它限定一個變量不允許被改變,產(chǎn)生靜態(tài)作用。使用const在一定程度上可以提高程序的安全性和可靠性。
const修飾的數(shù)據(jù)類型是指常類型,常類型的變量或?qū)ο蟮闹凳遣荒鼙桓碌摹?br> const 推出的初始目的,正是為了取代預(yù)編譯指令,消除它的缺點,同時繼承它的優(yōu)點
三、const與宏的區(qū)別
1.1 宏在預(yù)編譯時處理(宏在編譯開始之前就會被替換)
const會在編譯時被處理
1.2 define宏沒有類型,宏不做任何類型檢查,不會報編譯錯誤,只是替換
const常量有具體的類型,會編譯檢查,會報編譯錯誤
1.3 宏的好處:宏能定義一些函數(shù),方法。
const不能;使用大量宏,容易造成編譯時間久,每次都需要重新替換
1.4 宏僅僅是展開,有多少地方使用,就展開多少次,不會分配內(nèi)存。(宏定義不分配內(nèi)存,變量定義分配內(nèi)存。)
const常量會在內(nèi)存中分配(可以是堆中也可以是棧中)。
1.5 const 可以節(jié)省空間,避免不必要的內(nèi)存分配
| 宏 | const |
|---|---|
| #define PI 3.14159 //常量宏 | const doulbe Pi=3.14159; //此時并未將Pi放入ROM中 |
| double I=PI; //預(yù)編譯期間進行宏替換,分配內(nèi)存 | double i=Pi; //此時為Pi分配內(nèi)存,以后不再分配! |
| double J=PI; //再進行宏替換,又一次分配內(nèi)存 | double j=Pi; //沒有內(nèi)存分配 |
const定義常量從匯編的角度來看,只是給出了對應(yīng)的內(nèi)存地址,而不是象#define一樣給出的是立即數(shù),所以,const定義的常量在程序運行過程中只有一份拷貝(因為是全局的只讀變量,存在靜態(tài)區(qū)),而 #define定義的常量在內(nèi)存中有若干個拷貝。
1.6 提高了效率。 編譯器通常不為普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成為一個編譯期間的常量,沒有了存儲與讀內(nèi)存的操作,使得它的效率也很高。
2.1 const僅僅用來修飾右邊的變量
2.2 被const修飾的變量是只讀的
2.3 const簡單使用
//全局變量,constString1地址不能修改,constString1值能修改
const NSString *constString1 = @"I am a const NSString * string";
//意義同上,無區(qū)別
NSString const *constString2 = @"I am a NSString const * string";
// stringConst 地址能修改,stringConst值不能修改
NSString * const stringConst = @"I am a NSString * const string";
constString1 跟constString2 無區(qū)別.
*左邊代表指針本身的類型信息,const表示這個指針指向的這個地址是不可變的
*右邊代表指針指向變量的可變性,即指針存儲的地址指向的內(nèi)存單元所存儲的變量的可變性
四、const與static和extern配合使用
1.static的作用 ——局部變量(只在文件內(nèi)部使用)
1.1 延長局部變量的生命周期,程序結(jié)束才會銷毀
1.2 局部變量只會生成一份內(nèi)存,只會初始化一次
1.3 改變局部變量的作用域
1.4 只能在本文件中訪問,修改全局變量的作用域,生命周期不會改
1.5 避免重復(fù)定義全局變量
static NSString * const kConst = @"Hello";
static const CGFloat kWidth = 10.0;
2.extern的作用——全局變量(對外公開)
2.1 只是用來獲取全局變量(包括全局靜態(tài)變量)的值,不能用于定義變量
2.2 先在當前文件查找有沒有全局變量,沒有找到,才會去其他文件查找
extern常用在.h聲明中
//Test.h
extern NSString * const CLASSNAMEconst;
//Test.m
NSString * const CLASSNAMEconst = @"hello";
五、enum枚舉類型
枚舉常量不會占用對象的存儲空間,它們在編譯時被全部求值。枚舉常量的缺點是:它的隱含數(shù)據(jù)類型是整數(shù),其最大值有限,且不能表示浮點數(shù)(如PI=3.14159)。
typedef enum {
Third_None = -1,
Third_WEIXIN,
Third_QQ,Third_WEIBO
} ThirdType;
在iOS6和Mac OS 10.8以后Apple引入了兩個宏來重新定義這兩個枚舉類型,實際上是將enum定義和typedef合二為一,并且采用不同的宏來從代碼角度來區(qū)分。
NS_OPTIONS一般用來定義位移相關(guān)操作的枚舉值,我們可以參考UIKit.Framework的頭文件,可以看到大量的枚舉定義。
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone,//默認從0開始
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown,
};
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
從枚舉定義來看,NS_ENUM和NS_OPTIONS本質(zhì)是一樣的,僅僅從字面上來區(qū)分其用途。NS_ENUM是通用情況,NS_OPTIONS一般用來定義具有位移操作或特點的情況(bitmask)。
位移枚舉詳解
枚舉的定義還支持位運算的方式定義,就是NS_OPTIONS
特點1:等于號后面必須等于1
特點2:按照2進制位移位數(shù),確定數(shù)值
typedef NS_ENUM(NSInteger, Test)
{
TestA = 1, //1 1 1
TestB = 1 << 1, //2 2 10
TestC = 1 << 2, //4 3 100
TestD = 1 << 3, //8 4 1000
TestE = 1 << 4 //16 5 10000
};