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