iOS 不要用宏來定義你的常量

最近在工程里看到很多不規(guī)范的使用,于是來寫一篇博客來讓不是很清楚的小朋友們蜈彼,少埋點(diǎn)坑筑辨。

  • 首先,預(yù)處理命令他不是一個常量P夷妗9髟!还绘!

我們來看一段代碼

 #define avatar @"60"
    if (false) {
        #define avatar @"80"
    }
    NSLog(avatar);

這段代碼會輸出多少楚昭,我們將“avatar”定義為了60,然后在一個永遠(yuǎn)不會執(zhí)行的代碼里面重新定義了“avatar”為80蚕甥,if語句中的代碼永遠(yuǎn)不會執(zhí)行哪替,但是在編譯時期,編譯器會編譯這段代碼菇怀,而這個時候編譯器就會將avatar這個名字替換為@“80”凭舶,所以這段代碼最后的輸出結(jié)果就是80。
當(dāng)然這個時候編譯器是會有一個警告的爱沟,但是不知道有多少同學(xué)會忽略這個警告帅霜。或者你會告訴我你對警告十分敏感呼伸,不會放過他的身冀,但是記住你不是一個人在寫代碼,可能在別人的頁面他給你重新定義了你的define括享,給你挖了一個大坑搂根,還找不著.........

  • 用const來定義一個常量

const修飾符定義的變量是不可變的,比如說你需要定義一個動畫時間的常量铃辖,你可以這么做:

static const NSTimeInterval kAnimateDuration = 0.3;

當(dāng)你試圖去修改“ kAnimateDuration”的值的時候剩愧,編譯器會報錯。更加重要的是用這種方法定義的常量是帶有類型信息的娇斩,而這點(diǎn)則是define不具備的仁卷。

也許你已經(jīng)發(fā)現(xiàn)了,如果你像這樣定義:

static const NSString * kUserName = @"StrongX";

你是可以修改userName的值的犬第,(說好的常量呢~~~)

首先我們需要確定的是以下兩種寫法是一樣的:

static NSString const * kUserName = @"StrongX";
static const NSString * kUserName = @"StrongX";

也就是說const放在類型前還是類型后是一樣的效果锦积。然后不同效果的是下面這種寫法:

static NSString  * const kUserName = @"StrongX";

const 修飾的是他右邊的部分,也就是說:

static NSString const * kUserName = static NSString const (* kUserName )

static NSString  * const kUserName = static NSString  * const (kUserName)

當(dāng)const修飾的是(userName)的時候歉嗓,不可變的是userName;“*”在C語言中表示
指針指向符丰介,也就是說這個時候
userName指向的內(nèi)存塊地址不可變,而內(nèi)存保存的內(nèi)容是可變的,我們來做個嘗試:

 NSLog(@"內(nèi)存地址: %x",& kUserName);
    kUserName = @"superXLX";
    NSLog(@"內(nèi)存地址: %x",& kUserName);

以上NSLog會打印*userName指向的內(nèi)存塊地址基矮,而他的輸出是:

輸出

我們已經(jīng)發(fā)現(xiàn)當(dāng)我們改變內(nèi)存的內(nèi)存的時候他的地址并沒有發(fā)生改變淆储,也就是說這是符合“const”修飾符的規(guī)定的。
而當(dāng)我們的修飾符是這樣的時候:

static NSString  * const kUserName = @"StrongX";

我們則無法改變userName的值家浇。

所以當(dāng)我們需要定義一個不可變的常量的時候 本砰,我們還是需要將“const”修飾符放到“*”指針指向符后邊才對。

  • 一定要同時使用static和const來定義你的變量

上面已經(jīng)說了const是用來定義一個常量钢悲。而static在C語言中(OC中延用)則表明此變量只在改變量的輸出文件中可用(.m文件)点额,如果你不加“static”符號,那么編譯器就會對該變量創(chuàng)建一個“外部符號”莺琳,后果是什么呢还棱?
你可以嘗試在不同編譯文件中加入以下代碼:

NSString  * const kUserName = @"StrongX";

可能盡管文件之間并沒有相互引用,不存在屬性名重復(fù)的問題(因為這并不是一個屬性惭等,這是一個外部符號),但是編譯器還是報錯了:

目標(biāo)文件(.o)報錯

他會告訴你在兩個目標(biāo)文件(.0文件是.m文件編譯后的輸出文件)有一個重復(fù)的符號珍手。(OC中沒有類似C++中的名字空間的概念)
所以當(dāng)你在你自己的.m文件中需要聲明一個只有你自己可見的局部變量(k開頭)的變量的時候一定要同時使用“static”和“const”兩個符號。

  • 定義工程中的全局變量

在我們的工程中一定會定義很多全局常量辞做,很多人的做法是會創(chuàng)建一個“ constant.h”文件琳要,在這個文件中用#define聲明許多常量,然后將這個頭文件引入“pch”文件中秤茅,不能說這么做不對稚补,但是如同上面說的那樣define可能被修改,當(dāng)然在命名規(guī)范的情況下這種情況很少出現(xiàn)框喳,并且這樣做的效率很高课幕。
然而蘋果更推薦另外一種做法:"extern",這樣做的優(yōu)勢是保持常量絕對不會被修改五垮,并且一定初始化還帶有類型信息乍惊。
我們在"constants.h"文件中,聲明常量:

extern NSString *const XUserName;

然后在“constants.m”中定義他:

NSString *const XUserName = @"StrongX";

用“extern”定義的常量必須也只能初始化一次放仗,不滿足必須以及只能一次的條件那么編譯器就會提醒你污桦。在定義全局變量的時候需要要注意你的命名,你可以使用規(guī)定好的前綴來命名匙监。

“define”和“extern”各有各的優(yōu)勢,不過我個人還是比較推薦使用“extern”.(因為之前在一個工程中被define坑慘了——小作!)亭姥。

更多文章:http://www.StrongX.cn

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市顾稀,隨后出現(xiàn)的幾起案子达罗,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粮揉,死亡現(xiàn)場離奇詭異巡李,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)扶认,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門侨拦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辐宾,你說我怎么就攤上這事狱从。” “怎么了叠纹?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵季研,是天一觀的道長。 經(jīng)常有香客問我誉察,道長与涡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任持偏,我火速辦了婚禮驼卖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘综液。我一直安慰自己款慨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布谬莹。 她就那樣靜靜地躺著檩奠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪附帽。 梳的紋絲不亂的頭發(fā)上埠戳,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機(jī)與錄音蕉扮,去河邊找鬼整胃。 笑死,一個胖子當(dāng)著我的面吹牛喳钟,可吹牛的內(nèi)容都是我干的屁使。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼奔则,長吁一口氣:“原來是場噩夢啊……” “哼蛮寂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起易茬,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤酬蹋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體范抓,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡骄恶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了匕垫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片僧鲁。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖年缎,靈堂內(nèi)的尸體忽然破棺而出悔捶,到底是詐尸還是另有隱情,我是刑警寧澤单芜,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布蜕该,位于F島的核電站,受9級特大地震影響洲鸠,放射性物質(zhì)發(fā)生泄漏堂淡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一扒腕、第九天 我趴在偏房一處隱蔽的房頂上張望绢淀。 院中可真熱鬧,春花似錦瘾腰、人聲如沸皆的。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽费薄。三九已至,卻和暖如春栖雾,著一層夾襖步出監(jiān)牢的瞬間楞抡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工析藕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留召廷,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓账胧,卻偏偏與公主長得像竞慢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子治泥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 注:這是第三遍讀《C語言深度解剖》梗顺,想想好像自從大學(xué)開始就沒讀完過幾本書,其中譚浩強(qiáng)的那本《C語言程序設(shè)計(第四版...
    HavenXie閱讀 1,716評論 1 6
  • 目錄 內(nèi)存分配 變量:全局與局部 const变屁,static,extern 宏 結(jié)構(gòu)體意狠,枚舉(typeof與type...
    Ryan___閱讀 1,418評論 0 3
  • ### const,static,extern簡介 ### 一粟关、const與宏的區(qū)別(面試題): * `const...
    老騷鵝閱讀 651評論 0 7
  • 所有人都認(rèn)識我的秘密長什么樣子,但他們不知道這是個秘密环戈。就像是一張寫滿答案的試卷擺在面前闷板,卻沒人知道它屬于哪場考試。
    萌萌噠阿吹閱讀 79評論 0 0
  • 書院塞,一個有靈魂高檔商品遮晚。果真不同于如今的電子科技,用來用去都是同一個套路拦止,厭倦了县遣。同一價錢買來的書,其真正的用途在...
    xy78閱讀 214評論 0 1