整型數(shù)的使用規(guī)范

C語言中的整型有很多種,到了 Objective-C 中,除了這些類型外,又加入了 NSIntenger 等。

  • short
  • int
  • long
  • long long
  • NSIntenger
  • int8_t
  • int16_t
  • int32_t
  • int64_t

Long

在C語言中有時候我們需要比 int(32bit)范圍更大的整型狈网。而 long 的位數(shù)是由編譯器決定的,大部分C語言的編譯器會根據(jù)系統(tǒng)的位數(shù)來決定 long 的位數(shù)笨腥,在32位中 long 是32位(LONG_MAX=2147483647)拓哺,在64位中 long 是64位(LONG_MAX=9223372036854775807)。這種情況下脖母,在32位系統(tǒng)中我們就需要使用 long long int(64bit)士鸥,而在64位系統(tǒng)中則應(yīng)該使用 long int(64bit)。這對程序員來說是個很棘手的問題谆级,我們不可能根據(jù)系統(tǒng)位數(shù)來決定使用哪種類型烤礁。這時就應(yīng)該使用固定位數(shù)的 int8_t、int16_t肥照、int32_t脚仔、int64_t。他們的范圍分別對應(yīng)8bit舆绎、16bit鲤脏、32bit、64bit吕朵。所以猎醇,如果想要在多種平臺上都獲得較大的位數(shù),則應(yīng)該使用 int64_t边锁。

NSIntenger

NSIntenger 是 Objective-C 中新的整型數(shù)姑食,在 iOS 開發(fā)中我們也習(xí)慣使用 NSIntenger波岛。他的源代碼如下茅坛。

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

可以發(fā)現(xiàn),NSIntenger 與 long 的特性相似,位數(shù)都是根據(jù)系統(tǒng)位數(shù)來確定贡蓖。但是唯一的差距是曹鸠,NSIntenger 是通過預(yù)編譯來確定 NSIntenger 是重定義 int 還是 long,這在 Cocoa 的控制之下斥铺。NSInteger 的存在的原因是因為許多遺留的 API 使用不當(dāng)彻桃。在 iOS 沒有64位系統(tǒng)之前,如果 API 用 int 來持有有效的指針晾蜘,由于指針的位數(shù)是與系統(tǒng)位數(shù)保持一致的邻眷。這意味在64位系統(tǒng)中該 API 的不得不從 int 改為 long 才能正確記錄所有有效指針(如下代碼)。如果使用 NSInteger 則無需考慮這樣的問題剔交。根據(jù)我謹(jǐn)慎的猜測肆饶,long 的位數(shù)與系統(tǒng)位數(shù)保持一致,也應(yīng)該是由于這樣的原因岖常。但是相對于 NSIntenger 這種通過預(yù)編譯來控制的方式驯镊,long 對于蘋果來說明顯更加不可控。

隱患

知道了上述這些差異后竭鞍,就來舉兩個例子說明不了解這些差異可能帶來的隱患板惑。

用 int 儲存指針地址

- (NSUInteger)hash {
    long v1 = (long)((void *)_selector);
    long v2 = (long)_target;
    return v1 ^ v2;
}

這是 YYKit 中的一段代碼。這里如果使用 int 去儲存函數(shù)指針地址偎快,在64位的系統(tǒng)中則會有一半的地址因為越界變成 INT_MAX冯乘。

格式化 NSInteger

當(dāng)我們打印或格式化 NSInteger 時可能會時而遇到這樣的警告,時而又不會晒夹。

NSInteger test;
NSLog(@"%d", test);
NSInteger_Warning.png

這是因為往湿,當(dāng)我們用32位的手機(iPhone5s 以下)調(diào)試的時候,NSIntenger 其實就是int惋戏,所以沒有警告领追。當(dāng)我們拔掉數(shù)據(jù)線時,Xcode 會默認(rèn)選中“Generic iOS Device”响逢,而“Generic iOS Device”模擬的是64位的真機绒窑,這時 NSIntenger 就是 long,所以才會出現(xiàn)警告舔亭。當(dāng)我們切換模擬器時也會出現(xiàn)這樣的情況些膨。這就是為什么這樣的警告時而出現(xiàn)時而消失的原因。

占用空間

通過如下代碼對各種整型的占用的大小進(jìn)行打印钦铺。

short _short = 0;
int _int = 0;
long _long = 0;
long long _long_long = 0;
NSInteger _NSIntenger = 0;
int8_t _int8_t = 0;
int16_t _int16_t = 0;
int32_t _int32_t = 0;
int64_t _int64_t = 0;
NSLog(@"\nshort:%lu\n"
      "int:%lu\n"
      "long:%lu\n"
      "long long:%lu\n"
      "NSInteger:%lu\n"
      "int8_t:%lu\n"
      "int16_t:%lu\n"
      "int32_t:%lu\n"
      "int64_t:%lu\n",
      sizeof(_short),
      sizeof(_int),
      sizeof(_long),
      sizeof(_long_long),
      sizeof(_NSIntenger),
      sizeof(_int8_t),
      sizeof(_int16_t),
      sizeof(_int32_t),
      sizeof(_int64_t));

打印出來的結(jié)果如下:

64bit
short:2
int:4
long:8
long long:8
NSInteger:8
int8_t:1
int16_t:2
int32_t:4
int64_t:8

32bit
short:2
int:4
long:4
long long:8
NSInteger:4
int8_t:1
int16_t:2
int32_t:4
int64_t:8

根據(jù)打印信息我們發(fā)現(xiàn) short订雾、int 和 long long 不管在32位還是64位系統(tǒng)中他們的大小都是固定的。查看代碼發(fā)現(xiàn)矛洞,其實 int16_t洼哎、int32_t烫映、int64_t 就是簡單的重定義了 short、int噩峦、long long 而已锭沟。

更多

除了這些之外,Objective-C 中還重定義了大量類似的整數(shù)類型识补。

typedef unsigned char                   UInt8;
typedef signed char                     SInt8;
typedef unsigned short                  UInt16;
typedef signed short                    SInt16;
#if __LP64__
typedef unsigned int                    UInt32;
typedef signed int                      SInt32;
#else
typedef unsigned long                   UInt32;
typedef signed long                     SInt32;
#endif

UInt8族淮、SInt8、UInt16凭涂、SInt16祝辣、UInt32、SInt32 分別對應(yīng) uint8_t切油、int8_t较幌、uint16_t、int16_t白翻、NSInteger乍炉、NSUInteger。前四種相對后四種來說使用駝峰命名法滤馍,更符合Objective-C的風(fēng)格岛琼。他們均在 Core Framework 中大量使用。

使用

在 iOS 開發(fā)中我們習(xí)慣使用 NSIntenger巢株,因為 Cocoa 的 API 返回的數(shù)據(jù)類型大多是 NSIntenger槐瑞。而且,如果將來 iPhone 推出了新的系統(tǒng)架構(gòu)阁苞,NSIntenger 也可以保證你老項目中任何奇怪的代碼都不會出現(xiàn)隱患困檩。對于幾種簡單的場景,可以按照如下這樣使用那槽。

  1. 在簡單的循環(huán)中建議使用int悼沿。
  2. 成員/靜態(tài)/全局變量建議使用NSIntenger。
  3. 對較大范圍有強制要求時可以使用int64_t骚灸。
  4. 儲存顏色可以使用uint8_t糟趾。

除此之外,整型數(shù)還有很多種類型甚牲,他們都是根據(jù)C語言的基礎(chǔ)數(shù)據(jù)類型進(jìn)行重定義义郑。使用時可以根據(jù)代碼找到最終的數(shù)據(jù)類型和可能存在宏判斷結(jié)合 short、int丈钙、long非驮、long long 在32位和64位系統(tǒng)下大小的區(qū)別來推斷他們等價的類型。

博客:xuyafei.cn
簡書:jianshu.com/users/2555924d8c6e
微博:weibo.com/xuyafei86
Github:github.com/xiaofei86

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雏赦,一起剝皮案震驚了整個濱河市劫笙,隨后出現(xiàn)的幾起案子芙扎,更是在濱河造成了極大的恐慌,老刑警劉巖邀摆,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異伍茄,居然都是意外死亡栋盹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門敷矫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來例获,“玉大人,你說我怎么就攤上這事曹仗≌ヌ溃” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵怎茫,是天一觀的道長收壕。 經(jīng)常有香客問我,道長轨蛤,這世上最難降的妖魔是什么蜜宪? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮祥山,結(jié)果婚禮上圃验,老公的妹妹穿的比我還像新娘。我一直安慰自己缝呕,他們只是感情好澳窑,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著供常,像睡著了一般摊聋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上栈暇,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天栗精,我揣著相機與錄音,去河邊找鬼瞻鹏。 笑死悲立,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的新博。 我是一名探鬼主播薪夕,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼赫悄!你這毒婦竟也來了箭启?” 一聲冷哼從身側(cè)響起梅尤,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤哥蔚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后写隶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡讲仰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年慕趴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鄙陡。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡冕房,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出趁矾,到底是詐尸還是另有隱情耙册,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布毫捣,位于F島的核電站详拙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蔓同。R本人自食惡果不足惜溪厘,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望牌柄。 院中可真熱鬧畸悬,春花似錦、人聲如沸珊佣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咒锻。三九已至冷冗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惑艇,已是汗流浹背蒿辙。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留滨巴,地道東北人思灌。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像恭取,于是被迫代替她去往敵國和親泰偿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

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