《iOS知識點梳理-C語言》

知識點總結(jié)中,如有幸被您觀看,更有可能看到不足,期待指出交流

前言

C語言,開發(fā)的基礎(chǔ)功底,iOS很多高級應(yīng)用都要和C語言打交道.所以,C語言在iOS開發(fā)中的重要性是很厲害的.現(xiàn)在過來回顧這方面的問題.

查看下面的代碼會發(fā)生什么
least = MIN(*p++, b)

結(jié)果:((* p++) <= b) ? (* p++) :b),這個會產(chǎn)生副作用,指針p會做倆次++的自增操作

用預(yù)處理指令#define聲明一個常數(shù),用來表達一年中有多少秒(忽略閏年)
define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL(UL無符號長整型)
寫一個標(biāo)準(zhǔn)宏 MIN ,這個宏輸入倆個參數(shù)并返回較小的一個
define MIN(A,B) ((A) < (B) ? (A): (B))
給出以下代碼的輸出
int array[5] = {1,2,3,4,5};
int *p = &array[0];
int max = Max(*p++, 1);
printf("%d %d", max, *p);

答案:輸出的答案,1,2.
解析:看到宏的時候,就會想到宏的副作用,對于++、--,在宏的使用中會產(chǎn)生一系列的副作用,因此要慎用.下面是其宏的結(jié)構(gòu)

#define Max(X,Y) ((X)>(Y)?(X):(Y))
(*p++) > (1) ? (*p++) :(1)

先比較(1)>(1)>(p++):(1),然后p++了,這個時候p已經(jīng)指向了2,max為1,*p為2

define定義的宏和const定義的常量有什么區(qū)別
  • .#define定義宏的指令,程序在預(yù)處理階段將#define所定義的內(nèi)容只是進行了替換.所以在程序運行的時候,常量表中并沒有#define所定義的宏,系統(tǒng)不為他分配內(nèi)存.
  • .#define定義的宏指令,編譯的時候不會檢查數(shù)據(jù)類型,出錯的概率會更大
  • const定義的常量, 在程序運行的時候是存放在常量表中的,系統(tǒng)會給它分配內(nèi)存,編譯的時候會進行檢查
    注意: .#define定義表達式時要注意邊緣效應(yīng)例如
#define N 2 + 3 // 我們預(yù)想的值是5, 
int a = N / 2; // 結(jié)果就是 2 + 3 / 2 = 2.5,
關(guān)鍵字volatile有什么含義,舉出三個不同例子

優(yōu)化器在用到這個變量時必須每次都要小心的重新讀取這個變量的值,而不是使用保存在寄存器里面的備份.下面是例子

  • 并行設(shè)備的硬件寄存器(如:狀態(tài)氣純器)
  • 一個終端服務(wù)字程勛中會訪問到的非自動變量(Non-automatic variables)
  • 多線程應(yīng)用中唄幾個任務(wù)共享的變量
完成字符拷貝可以使用sprintf空猜、strcpy绽慈、以及memcpy函數(shù),這些有什么區(qū)別

這些函數(shù)的區(qū)別在于實現(xiàn)功能以及操作的對象不同

  • strcpy: 函數(shù)操作的對象是字符串,完成從源字符串到目的字符串的拷貝功能.
  • sprintf:這個函數(shù)主要用來實現(xiàn)(字符串或基本數(shù)據(jù)類型)向字符串的轉(zhuǎn)換功能.如果元對象是字符串,并且制定%s格式符,也可實現(xiàn)字符串拷貝功能.
  • memcpy: 函數(shù)顧名思義就是內(nèi)存拷貝,實現(xiàn)建一個內(nèi)存塊的內(nèi)容復(fù)制到另一個內(nèi)存塊這個功能.類存款由對象的其實地址和內(nèi)存長度信息,并且對象具有可操作性即可.鑒于memcpy函數(shù)的長拷貝的特點以及數(shù)據(jù)類型代表的物理意義,memcpy函數(shù)通常限于同種類型數(shù)據(jù)或?qū)ο笾g的拷貝,其中當(dāng)然也包括字符串拷貝以及基本數(shù)據(jù)類型的拷貝.
    對于拷貝字符串,上述的三個函數(shù)都是可以實現(xiàn)的但是實現(xiàn)的效率和使用的方便程度不一樣
  • strcpy 最合適的選擇,效率高切調(diào)用方便
  • snprintf 要額外指定格式符并且進行格式轉(zhuǎn)換,麻煩而且不高效
  • memcpy 雖然高效, 但是需要額外提供拷貝的內(nèi)存長度這一個參數(shù),易錯而且使用不方便.并且長度過道,還會帶來性能的下降.
  • 對于非字符串的賦值strcpy和 snprintf 就不行了.這個時候就只能用 memcpy來拷貝了
    static關(guān)鍵字的作用
  • 隱藏,編譯多個文件時,所有未加static前綴的全局變量和函數(shù)都全局可見
  • 保持變量內(nèi)容的持久.全局變量和static變量都純純在靜態(tài) 存儲區(qū),程序開始運行就初始化,只初始化一次,static控制變量的作用范圍.
  • 默認(rèn)初始化為0,在靜態(tài)數(shù)據(jù)區(qū),內(nèi)存中的所有直接都是0x00,全局變量和static變量都是默認(rèn)初始化0

static的特別

  • static全局變量和普通的全局變量有什么區(qū)別:static全局變量只初始化一次,防止在其他文件單元中被應(yīng)用
  • static局部比啊年和普通局部變量有什么區(qū)別:static局部變量只被初始化一次,洗一次依據(jù)上一次的結(jié)果值,
  • static函數(shù)和普通函數(shù)有什么區(qū)別:static函數(shù)在內(nèi)存中只有一份,普通函數(shù)在每個被調(diào)用中維持一份拷貝
    想看的具體一點可以看下面的文章
    Static關(guān)鍵字理解(iOS)
    關(guān)鍵字const
  • const int a; int const a; 作用一樣, a是一個長整型數(shù)
  • const int a; int const a;a是一個紙箱長整數(shù)的指針(整型數(shù)是不可修改的,但是指針可以)
  • int * const a; a 是一個紙箱整型數(shù)的常指針(真正指向的整型數(shù)是可以修改的,但指針是不可以修改的)
  • int const *const a; a 是一個紙箱常整數(shù)的常指針(指針指向的整型數(shù)是不可修改的, 同事指針也是不可修改的)
    Const 關(guān)鍵字理解(iOS)
堆棧
  • 管理方式:對于棧來說,是有編譯器自動管理,無需我們手工控制;對于堆來說,釋放工作是有程序員控制,容易產(chǎn)生內(nèi)存泄漏.
  • 申請大小:
    -- 棧:在windows下,棧是向低地址擴展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域.這句話的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的,在windows下,棧的大小是2M(也有的說是1M,總之是編譯時就確定的參數(shù)),如果申請的空間超過棧剩余空間時,就會提示 overflow.因此能從棧獲得的空間小
    -- 堆:堆是向高地址擴展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域.這是由于系統(tǒng)是用鏈表來存儲的空閑內(nèi)存地址的,自然是不連續(xù)的,二鏈表的遍歷方向是由低地址向高地址.堆的大小受限于計算機系統(tǒng)中有效的虛擬內(nèi)存.由此可見,堆獲取的空間比較活,也比較大.
  • 碎片問題:對于堆來講,頻繁的new/delete勢必會造成內(nèi)存空間的不連續(xù),從而造成大量的碎片,使程序效率低下,對于棧來講,就不會存在這個問題,因為棧是先進后出的隊列,他們是如此的一一對應(yīng),以至于永遠(yuǎn)都不可能有一塊內(nèi)存塊從棧中彈出
  • 分配方式:堆都是動態(tài)分配,沒有靜態(tài)分配的堆.棧有倆種分配方式:靜態(tài)分配和動態(tài)分配.靜態(tài)分配是編譯器完成的,比如局部變量的分配.動態(tài)分配由alloc函數(shù)進行分配,但是棧的動態(tài)分配和堆是不同的,他的動態(tài)分配是由編輯器進行釋放,無需我們手工實現(xiàn).
  • 分配效率:棧是及其系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu),計算機會在底層對棧提供支持:分配專門的寄存器存在放棧的地址,壓棧出棧都有專門的指令執(zhí)行,這就決定了棧的效率比較高.堆則是c/c++函數(shù)庫提供的,他的機制很復(fù)雜的.
數(shù)組和指針的區(qū)別
  • 數(shù)組可以申請在棧區(qū)和數(shù)據(jù)區(qū):指針可以指向任意類型的內(nèi)存塊,sizeof作用于數(shù)組時,得到的是數(shù)組所占的內(nèi)存大小,作用于指針時,得到的都是4個字節(jié)的大小.
  • 數(shù)組名標(biāo)識數(shù)組的首地址,是常量指針,不可修改指向.比如不可以將++作用于數(shù)組名上;普通指針的值可以改變,比如可將++作用于指針上
  • 用字符串初始化字符數(shù)組是將字符串的內(nèi)容拷貝到字符數(shù)組中;用字符串初始化字符指針是將字符串的首地址賦值給指針,也就是指針指向了該字符串
引用和指針的區(qū)別
  • 指針指向一塊內(nèi)存, 內(nèi)存儲存所指向內(nèi)存的地址
  • 引用是某塊內(nèi)存的別名
  • 引用時不需要解引用(*)而指針需要
  • 引用只在定義時唄初始化,之后不可變,指針可變
  • 引用沒有const
  • 引用不能為空
  • sizof引用得到的是所指向變量(對象)的大小,sizeof指針是指針本身的大小
  • 指針和引用的自增(++)運算意義不一樣:引用++未引用對象自己++.指針++是真想對象后面的內(nèi)存.
  • 程序需要尾指針分配內(nèi)存區(qū)域,引用不需要
用變量a給出下面的定義
  • (1)一個整型數(shù)
  • (2)一個指向整型數(shù)的指針
  • (3)一個指向指針的指針,它指向指針是指向一個整型數(shù)
  • (4)一個有10個整型數(shù)的數(shù)組
  • (5)一個有10個指針的數(shù)組,該指針是指向一個整型數(shù)的
  • (6)一個指向有10個整型數(shù)數(shù)組的指針
  • (7)一個指向函數(shù)的指針,該函數(shù)有一個整型參數(shù)并返回一個整型數(shù)
  • (8)一個有10個指針的數(shù)組,該指針指向一個函數(shù),該函數(shù)有一個整型參數(shù)并返回一個整數(shù)型
(1)int a;
(2)int *a;
(3)int **a;
(4)int a[10]
(5)int *a[10]
(6)int (*)a[10]
(7)int (*)a(int)
(8)int (*a[10])(int)

請寫出以下代碼輸出

int a[5] = {1,2,3,4,5}
int *ptr = (int *)(&a+1);
printf("%d, %d", *(a+1), *(ptr + 1));

參考答案:2,隨機值
分析:a代表有5個元素的數(shù)組的首地址,a[5]的元素分別是1,2,3,4,5.接下來,a+1表示數(shù)據(jù)首地址加1,那么就是a[1],對應(yīng)的值也就是2.但是,這里是&a+1,因為a代表的是整個數(shù)組,他的空間大小為5sizeof(int),因此&a+1就是a+5.a是個常量指針,指向當(dāng)前數(shù)組的首地址,指針+1就是移動sizeof(int)個字節(jié).因此,ptr是指向int 類型的指針,而ptr 指向的就是a+5,那么ptr+1也就相當(dāng)于a + 6,所有最后一個(ptr + 1)就是一個隨機值了.而(ptr-1)就相當(dāng)于a+4,對應(yīng)的值就是5.

簡述內(nèi)存分區(qū)情況
  • 代碼區(qū): 存放函數(shù)二進制代碼
  • 數(shù)據(jù)區(qū): 系統(tǒng)運行時申請內(nèi)存并初始化,系統(tǒng)推出時由系統(tǒng)示范,存放全區(qū)變量,靜態(tài)變量,常量
  • 堆區(qū):通過malloc等函數(shù)或new等操作浮動動態(tài)申請得到,需要程序員手動申請和釋放.
  • 棧區(qū):函數(shù)模塊內(nèi)申請,函數(shù)結(jié)束時由系統(tǒng)自動釋放,存放局部變量,函數(shù)參數(shù)
用NSLog函數(shù)輸出一個浮點類型,結(jié)果四舍五入,并保留一位小數(shù)
float money = 1.011;
NSLog(@"%.1f",money);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市辈毯,隨后出現(xiàn)的幾起案子坝疼,更是在濱河造成了極大的恐慌,老刑警劉巖谆沃,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钝凶,死亡現(xiàn)場離奇詭異,居然都是意外死亡唁影,警方通過查閱死者的電腦和手機腿椎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門桌硫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人啃炸,你說我怎么就攤上這事铆隘。” “怎么了南用?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵膀钠,是天一觀的道長。 經(jīng)常有香客問我裹虫,道長肿嘲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任筑公,我火速辦了婚禮雳窟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匣屡。我一直安慰自己封救,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布捣作。 她就那樣靜靜地躺著誉结,像睡著了一般。 火紅的嫁衣襯著肌膚如雪券躁。 梳的紋絲不亂的頭發(fā)上惩坑,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機與錄音也拜,去河邊找鬼以舒。 笑死,一個胖子當(dāng)著我的面吹牛慢哈,可吹牛的內(nèi)容都是我干的稀轨。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼岸军,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了瓦侮?” 一聲冷哼從身側(cè)響起艰赞,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肚吏,沒想到半個月后方妖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡罚攀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年党觅,在試婚紗的時候發(fā)現(xiàn)自己被綠了雌澄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡杯瞻,死狀恐怖镐牺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情魁莉,我是刑警寧澤睬涧,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站旗唁,受9級特大地震影響畦浓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜检疫,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一讶请、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧屎媳,春花似錦夺溢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晒来,卻和暖如春钞诡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背湃崩。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工荧降, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人攒读。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓朵诫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親薄扁。 傳聞我的和親對象是個殘疾皇子剪返,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

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