1.寫出下面代碼的運行結(jié)果
? ? int array[5] = {1, 2, 3, 4, 5};int *p = &array[0];
? ? int max = Max(*p++, 1);
? ? printf("%d ,%d", max, *p);
? ? 答案:1,2
? ? #define Max(X, Y) ((X) > (Y) ? (X) : (Y)) 對于++摄乒、--在宏定義當中使用最容易產(chǎn)生副作用
2.define 定義的宏和const 定義的常量的區(qū)別
? ? ?#define定義的宏,程序在預(yù)處理階段將宏定義內(nèi)容僅進行了替換叠纷,因此程序運行時,常量表中沒有用 ? ? #define所定義的宏,系統(tǒng)并不會為它分配內(nèi)存,而且在編譯時不會檢查數(shù)據(jù)類型陋率,出錯的概率要大一些。
? ? const 定義的常量秽晚,在程序運行的時候是存放在常量表中瓦糟,系統(tǒng)會為它分配內(nèi)存,而且在編譯時進行數(shù)據(jù)類型檢查赴蝇。
? ? #define 定義的表達式時要注意“邊緣效應(yīng)”菩浙,例如如下定義:
? ? #define N 2+3 // 我們預(yù)想的 N 值是5,我們這樣使用N
? ? int a = N / 2 ; // 我們預(yù)想的 a 的值是2.5,可實際上 a 的值是3.5
3.strcpy , memcpy , sprintf 使用注意事項
? ? strcpy 是一個字符串拷貝函數(shù)劲蜻,原型為:strcpy ( char destr, const char str ) ,結(jié)束標志為?‘\0’ ,由于拷貝的長度不是我們控制的陆淀,所以拷貝容易出錯。
? ? Memcpy 是一個內(nèi)存拷貝函數(shù)先嬉,函數(shù)原型為:memcpy (char destrc , const char str, unsigned int len ),講長度為 len 的一段內(nèi)存轧苫,從str 拷貝到 destrc 中去,這個函數(shù)的長度可控疫蔓,但是會有內(nèi)存讀寫錯誤含懊,(比如 len 的長度大于要拷貝的空間或者目的空間)
? ? sprintf 是一個格式化函數(shù),將一段數(shù)據(jù)從通過特定的格式衅胀,格式化到一個字符串緩沖區(qū)中去岔乔。sprintf 格式化的函數(shù)的長度不可控制,有可能格式化后的字符串會超出緩沖區(qū)的大小滚躯,造成溢出雏门。
4.static 關(guān)鍵字的作用
? ? · 隱藏。編譯多個文件時掸掏,所有未加 static 前綴的全局變量和函數(shù)都全局可見茁影。
? ? · 保持變量內(nèi)容的持久。全局變量和 static 變量都存儲在靜態(tài)存儲區(qū)阅束,程序開始運行就初始化呼胚,只初始化一次。static 控制了變量的作用范圍息裸。
? ? · 默認初始化為0蝇更。在靜態(tài)數(shù)據(jù)區(qū),內(nèi)存中的所有字節(jié)都是0x00呼盆,全局變量和 static 變量都是默認初始化為0年扩。
5.static 關(guān)鍵字的區(qū)別
? ? · 全局變量方面:static 全局變量只初始化一次,防止在其他文件單元中被引用访圃;
? ? · 局部變量方面:static 局部變量只被初始化一次厨幻,下一次依據(jù)上一次結(jié)果的值;
? ? · 函數(shù)方面 :static 函數(shù)在內(nèi)存中只有一份腿时,普通函數(shù)在每個被調(diào)用中維持一份拷貝
6.關(guān)鍵字 const
? ? · int const a 况脆;const int a :作用一樣,a 是一個常整型數(shù)
? ? · int const * a 批糟;const int * a :a 是一個指向常整型數(shù)的指針(整型數(shù)不可變格了,指針可變)
? ? · int * const a :a 是一個指向整型數(shù)的常指針(整型數(shù)可變,指針不可變)
? ? · int const *const a :是一個指向常整型數(shù)的常指針(指針徽鼎、整型數(shù)均不可變)
7.堆和棧
? ? · 管理方式:
? ? ? ? 棧:由編譯器自動管理盛末,無需我們手工控制
? ? ? ? 堆:釋放工作由程序員控制弹惦,容易產(chǎn)生內(nèi)存泄漏(memory leak)。
? ? · 申請大星牡:
? ? ? ? 棧:在 Windows 下棠隐,棧是向低地址擴展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存區(qū)域檐嚣,即棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的助泽,在 Windows 下棧的大小是2M (也有的說是 1 M ),如果申請的空間超過棧的剩余空間時净嘀,將提示 overflow报咳。因此能從棧獲取的空間比較小侠讯。
? ? ? ? 堆:是向高地址擴展的數(shù)據(jù)結(jié)構(gòu)挖藏,是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表存儲空閑的內(nèi)存地址的厢漩,自然不連續(xù)膜眠,而鏈表的遍歷方式是由低地址向高地址。堆得大小受限于計算機系統(tǒng)中有效的虛擬內(nèi)存溜嗜,所以堆獲得的空間比較靈活宵膨,也比較大。
? ? · 碎片問題:
? ? ? ? 棧:不存在該問題炸宵,因為棧是先進后出的隊列辟躏,他們是如此一一對應(yīng),以至于沒有一個內(nèi)存塊從棧中間彈出
? ? ? ? 堆:頻繁的 new/delete 勢必造成空間的不連續(xù)土全,從而造成大量的碎片捎琐,使程序效率降低
? ? · 分配方式:
? ? ? ? 棧:有2種方式:靜態(tài)和動態(tài)分配。靜態(tài)分配是由編譯器完成的裹匙,比如局部變量的分配瑞凑。動態(tài)分配由 alloc 函數(shù)進行分配,但棧的動態(tài)分配和棧不同概页,是由編譯器進行釋放籽御,無需程序員手工實現(xiàn)
? ? ? ? 堆:只有動態(tài)分配
? ? · 分配效率:
? ? ? ? 棧:是機器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu),計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址惰匙,壓棧出棧都有專門的指令執(zhí)行技掏,所以效率比較高
? ? ? ? 堆:是C/C++ 函數(shù)庫提供的,機制很復(fù)雜
8.引用和指針的區(qū)別
? ? · 指針指向一塊內(nèi)存项鬼,內(nèi)容存儲所指內(nèi)存的地址哑梳;引用是某塊內(nèi)存的別名。
? ? · 指針使用時需(*)秃臣,引用不需要涧衙。
? ? · 引用只在定義時被初始化哪工,之后不可變;指針可變弧哎。
? ? · 引用沒有const雁比。
? ? · 引用不能為空坟冲。
? ? · sizeof 引用得到的是所指向變量(對象)的大小钦幔,sizeof 指針是指針本身的大小。
? ? · 引用 ++ 為引用對象自己 ++ 讳癌,指針 ++ 是指向?qū)ο蠛竺娴膬?nèi)存序攘。
? ? · 程序需要為指針分配內(nèi)存區(qū)域茴她,引用不需要。
9.用變量 a 給出下面的定義
? ? · 一個有10個整型數(shù)的數(shù)組:
? ? ? int a [10]
? ? · 一個有10個指針的數(shù)組程奠,該指針是一個指向一個整型數(shù)的:
? ? ? int * a [10]
? ? · 一個指向10個整數(shù)數(shù)組的指針:
? ? ? int ( * ) a [10]
? ? · 一個指向函數(shù)的指針丈牢,該函數(shù)有一個整型參數(shù)并返回一個整型數(shù):
? ? ? int ( * ) a ( int )
? ? · 一個有10個指針的數(shù)組,該指針指向一個函數(shù)瞄沙,該函數(shù)有一個整型參數(shù)并返回一個整型參數(shù)
? ? ? int ( * a [10] ) ( int )
10.寫出以下代碼的輸出
? ? 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 ],值為2诬滩。但這里是&a + 1霹粥,因為 a 代表的是整個數(shù)組,它的空間大小為5 * sizeof ( int )碱呼,因此 &a + 1就是 a + 5蒙挑。a 是個常量指針,指向當前數(shù)組的首地址愚臀,忆蚀,指針 + 1就是移動sizeof( int )個字節(jié)。因此 ptr 是指向 int * 類型的指針姑裂,而 ptr 指向的就是 a + 5馋袜,那么 ptr +1 也相當于 a + 6,所以最后的 *( ptr +1)就是一個隨機值了舶斧。而 *( ptr - 1 )就相當于 a + 4欣鳖,對應(yīng)值為5。
11.內(nèi)存分區(qū)情況
? ? · 代碼區(qū):存放函數(shù)二進制代碼
? ? · 數(shù)據(jù)區(qū):系統(tǒng)運行時申請內(nèi)存并初始化茴厉,系統(tǒng)退出時由系統(tǒng)釋放泽台,存放全局變量什荣、靜態(tài)變量、常量
? ? · 堆區(qū):通過 malloc 等函數(shù)或 new 等操作符動態(tài)申請得到怀酷,需程序員手動申請和釋放
? ? · 棧區(qū):函數(shù)模塊申請稻爬,函數(shù)結(jié)束時由系統(tǒng)自動釋放,存放局部變量蜕依、函數(shù)參數(shù)
12.用NSLog輸出一個浮點類型桅锄,結(jié)果四舍五入,并保留一位小數(shù)
? ? float money = 1.011样眠;
? ? NSLog ( @"%.1f", money ) ;
13.指針和數(shù)組的區(qū)別
? ? · 數(shù)組可以申請在棧區(qū)和數(shù)據(jù)區(qū)友瘤;指針可以指向任意類型的內(nèi)存塊。sizeof 作用于數(shù)組時檐束,得到是數(shù)組所占的內(nèi)存大斜柩怼;作用于指針時厢塘,得到的都是4個字節(jié)的大小
? ? · 數(shù)組名表示數(shù)組首地址茶没,是常量指針,不可修改指向晚碾;普通指針的值可以改變
? ? · 用字符串初始化字符數(shù)組是將字符串的內(nèi)容拷貝到字符數(shù)組中;用字符串初始化字符指針是將字符串的首地址賦給指針喂急,也就是指向了該字符串