第一阶段.C语言
一.C語言基礎(chǔ)考題
1.預(yù)處理
1.預(yù)編譯最先工作的是啥?
答:編譯#開頭的指令,,如 拷貝#include 包含的頭文件代碼,#define 宏定義的替換,條件編譯 ifndef
2.c 語言中 # 與 ##的區(qū)別以及作用?
答::# :把宏參數(shù)變成一個字符串; ## :把兩個宏參數(shù)連接到一起(只能兩個
3.如何避免頭文件被重復(fù)包含?
答:應(yīng)用#ifndef #define #endif
2.關(guān)鍵字
?1. static 關(guān)鍵字的作用?
C語言中static關(guān)鍵字的作用 - Practical - 博客園
?2.const關(guān)鍵字的作用?
①對變量加以限定不能被修改,常量必須在定義的時候同時被初始化。
②const 和指針一起使用,
const int *p1;
int const *p2;
int *const p3;
在三種情況中,第三種指針是只讀的,p3 本身的值不能被修改; 第一二種情況,指針?biāo)赶虻臄?shù)據(jù)是只讀的,p1,p2 的值可以修改,但指向的數(shù) 據(jù)不能被修改。
③const 和函數(shù)形參一起使用 使用 const 單獨定義變量可以用#define 命令替換,const 通常放在函數(shù)形參中。 如果形參是一個指針,為了防止在函數(shù)內(nèi)部修改指針指向的數(shù)據(jù)就可以用 const 來限制
3.volatile 關(guān)鍵字的作用?
編譯優(yōu)化的方法有:將內(nèi)存變量緩存到寄存器;調(diào)整指令順序充分利用 CPU 指 令流水線。
答:因為訪問寄存器要比訪問內(nèi)存單元要快的多,編輯器會作減少存取的優(yōu)化。 當(dāng)使用 volatile 聲明函數(shù)變量的時候,系統(tǒng)總是重新從它所在的內(nèi)存讀取數(shù)據(jù)。 遇到這個關(guān)鍵字聲明的變量,編譯器對訪問該變量的代碼不再進(jìn)行優(yōu)化,從而提 供對特殊地址的穩(wěn)定訪問; 如果不使用 valatile,編譯器將對所聲明的語句進(jìn)行 優(yōu)化,以免出錯。
4. extern 關(guān)鍵字的作用?
答: ①函數(shù)內(nèi)的局部變量,函數(shù)外定義的變量為全局變量,為靜態(tài)存儲方式,生存周 期為整個程序,有效范圍為定義變量的位置開始到本源文件結(jié)束。 如果在定義前想要引用該全局變量,則應(yīng)該加上 extern 作為 “外部變量聲明”。 多個源文件的工程想要引用一個源文件的外部變量也只許引用變量的文件中加 入 extern 關(guān)鍵字加以聲明,但是可以在引用的模塊內(nèi)修改其變量的值,慎用。 ②extern “C”: C++代碼調(diào)用 C 語言代碼。在 C++的頭文件中使用
3.結(jié)構(gòu)體
1.結(jié)構(gòu)體位域的好處?
①并不需要完整的字節(jié),節(jié)省存儲空間,處理簡單;
②方便利用位域把一個變量按位域分解
2.*計算一個結(jié)構(gòu)體的大小
①結(jié)構(gòu)體偏移量的概念: 結(jié)構(gòu)體中的偏移量指的是一個成員的實際地址和結(jié)構(gòu)體首地址之間的距離。
②結(jié)構(gòu)體大小的計算方法: 結(jié)構(gòu)體會涉及到字節(jié)對齊,(目的是為了讓計算機(jī)快速讀取,用空間交換速度), 即最后一個成員的大小+最后一個成員的偏移量+末尾的填充節(jié)數(shù)。
第一步:結(jié)構(gòu)體成員的偏移量必須是成員大小的整數(shù)倍(0被認(rèn)為任何數(shù)的整數(shù)倍)
第二步:結(jié)構(gòu)體大小必須是所有成員的整數(shù)倍(數(shù)組和結(jié)構(gòu)體除外)
列子1:
Struct s1{
char ch1;? // 1
?int i;? ? ? ? // 4+3
char ch2;
}
計算出的結(jié)構(gòu)體大小是 12,而不是 9。
列子2:
Struct s2{
char ch1;? // 1
?int i;? ? ? ? // 4+3
? ? ?Struct s1{
? ? ? ? ?char ch1;?
? ? ? ? ?int i;? ? ? ?}
?float ch2;? ?//4
}
此時,結(jié)構(gòu)體大小為12,中間的聲明不占空姐,而
Struct s2{
char ch1;? // 1
?int i;? ? ? ? // 4+3
? ? ?Struct s1{
? ? ? ? ?char ch1;?
? ? ? ? ?int i;? ?
? ?}temp;
?float ch2;? ?//4
}
此時結(jié)構(gòu)體的大小為20。
注:聯(lián)合體只算其中成員最大的。
#pragma pack(4) //指定向4對齊,如果最大成員大于4,按4對齊,如果最大成員小于4,則按最大成員對齊
4.c語言基本概率
1. 引用與指針的區(qū)別:
①引用必須初始化,指針不必初始化
②引用初始化后不能改變,但是指針可以改變所指的對象
③不存在空值的引用,但是存在空值的指針
2. .h 頭文件中, ifndef /define /endif 的作用
①防止頭文件被重復(fù)調(diào)用
3. include和 includ”file.h”的區(qū)別?
①前者從編譯器自帶的庫函數(shù)中尋找文件,從標(biāo)準(zhǔn)庫路徑開始搜索文件
②后者是從自定義的文件中尋找文件,尋找不到再到庫函數(shù)中尋找文件
4. 全局變量和局部變量的區(qū)別?
①全局變量->存儲在靜態(tài)數(shù)據(jù)區(qū),占用靜態(tài)的存儲單元
②局部變量->存儲在棧中,只有在函數(shù)被調(diào)用過程中才開始分配存儲單元
5. 堆棧溢出的原因有哪些?
①函數(shù)調(diào)用層次太深,函數(shù)遞歸調(diào)用時,系統(tǒng)要在棧中不斷保存函數(shù)調(diào)用時的線 程和產(chǎn)生的變量,遞歸調(diào)用太深,會造成棧溢出,這是遞歸無法返還。
②動態(tài)申請空間使用后沒有釋放。由于 C 語言中沒有垃圾資源自動回收機(jī)制,因 此需要程序員主動釋放已經(jīng)不再使用的動態(tài)地址空間。
③數(shù)組訪問越界,C 語言沒有提供數(shù)組下標(biāo)越界檢查,如果在程序中出現(xiàn)數(shù)組下 標(biāo)訪問超出數(shù)組范圍,運行過程中可能會存在內(nèi)存訪問錯誤。
④指針非法訪問,指針保存了一個非法地址,通過這樣的指針訪問所指向的地址 時會產(chǎn)生內(nèi)存訪問錯誤
7. 局部變量能否與全局變量重名?
能,局部變量會屏蔽 全局變量,要使用全局變量,需使用”::”; 局部變量可以與全局變量同名,在函數(shù)內(nèi)引
8. 如何引用一個已經(jīng)定義了的全局變量?
①用 extern 關(guān)鍵字方式
②用引用頭文件方式,前提是其中只能有一個 C 文件中對此變量賦初值,此時連 接不會出錯。
9. 全局變量可不可以定義在可被多個.c 文件包含的頭文件中,為啥?
可以,在不同的 C 文件中各自用 static 聲明的全局變量,變量名可能相同,但是 各自 C 文件中的全局變量的作用域為該文件,所以互不干擾用這個變量時,會用到同名的局部變 量,而不會用到全局變量
11.static 關(guān)鍵字在 全局變量、局部變量、函數(shù)的區(qū)別?
①全局變量+static :改變作用域,改變(限制)其使用范圍。 只初始化一次,防止在其他文件單元中被引用。 全局變量的作用域是整個 源程序,在各個源文件中都是有效的,而加了靜態(tài)后的全局變量的作用域 僅限 于一個源文件中。
②局部變量+static :改變看它的存儲方式,也就是改變了它的生存期。
③普通函數(shù)+static :作用域不同,僅在本文件。 只在當(dāng)前源文件中使用的函數(shù)應(yīng)該說明為內(nèi)部函數(shù)(static),內(nèi)部函數(shù)應(yīng)該 在當(dāng)前源文件中說明和定義,對于可在當(dāng)前源文件以外使用的函數(shù),應(yīng)該在一個 頭文件中說明,要使用這些函數(shù)的源文件要包含這個頭文件
12.程序的內(nèi)存分配(???#xff09; 前言:c 語言程序.c 文件經(jīng)過編譯連接后形成編譯、鏈接后形成的二進(jìn)制映像文 件由堆,、棧、數(shù)據(jù)段(只讀數(shù)據(jù)段,未初始化數(shù)據(jù)段 BSS,已初始化數(shù)據(jù)段三 部分)、代碼段組成。
①棧區(qū) (stack):由編譯器進(jìn)行管理,自動分配和釋放,存放的是函數(shù)調(diào)用過 程中的各種參數(shù),局部變量,返回值以及函數(shù)返回地址。
②堆區(qū)(heap) :用于程序動態(tài)申請分配和釋放空間,malloc 和 free,程序員 申請的空間在使用結(jié)束后應(yīng)該釋放,則程序自動收回。
③全局(靜態(tài))存儲區(qū):分為 DATA(已經(jīng)初始化),BSS(未初始化)段,DATA 段存放的是全局變量和靜態(tài)變量; BSS(未初始化)存放未初始化的全局變量和 靜態(tài)變量。 程序運行結(jié)束后自動釋放,其中 BSS(全部未初始化區(qū))會被系統(tǒng)自動 清零。
④文字常量區(qū) :存放常量字符串,程序結(jié)束后由系統(tǒng)釋放。
⑤程序代碼段:存放程序的二進(jìn)制代碼
13.解釋”堆”和”棧”的區(qū)別:
注:被問到這個問題的時候可以從這幾個方面進(jìn)行闡述 ①申請方式②申請后的系統(tǒng)反應(yīng)③申請內(nèi)存的大小限制④申請效率⑤存儲內(nèi)容⑥分配方式
①申請方式: Strack(棧): 由編譯器自帶分配釋放,存放函數(shù)的參數(shù)值,局部變量等。 Heap(堆):程序員自己申請,并指名大小-->malloc 函數(shù)。
②申請后的系統(tǒng)響應(yīng) Strack(棧):只要棧剩余空間>所申請空間,都會提供。 Heap(堆):操作系統(tǒng)有記錄空閑內(nèi)存的鏈表:收到申請->遍歷鏈表->尋找->申請空間的堆 結(jié)點
③申請內(nèi)存的大小限制 Strack(棧):向低地址擴(kuò)展的數(shù)據(jù)結(jié)果,連續(xù)內(nèi)存區(qū)域,棧 獲得的空間較小。 Heap(堆):向高地址擴(kuò)展的,不連續(xù)內(nèi)存區(qū)域;鏈表遍歷方向為(低地址->高地址)。 棧獲得空間靈活,空間也大。
④申請效率 Strack(棧):系統(tǒng)自由分配,速度快。 Heap(堆):速度慢,容易產(chǎn)生內(nèi)存碎片。
⑤存儲內(nèi)容 Strack(棧):第一進(jìn)棧 :主函數(shù)中的下一條指令的地址 -->函數(shù)的各個參數(shù),參數(shù)由右往左 進(jìn)棧。-->函數(shù)的局部變量(靜態(tài)變量不入棧)。調(diào)用結(jié)束后,順序相反,局部變量先出棧。 Heap(堆): 程序員自己安排
⑥分配方式 Strack(棧):棧 有兩種分配方式,靜態(tài)分配和動態(tài)分配。靜態(tài)分配是編譯器完成的,比如局 部變量的分配,動態(tài)分配由 alloca 函數(shù)進(jìn)行分配,但棧的動態(tài)分配和堆是不同的,棧的動態(tài) 內(nèi)存由編譯器進(jìn)行釋放,無需手工實現(xiàn)。 Heap(堆):堆都是動態(tài)分配的,沒有靜態(tài)分配的堆。
14. 結(jié)構(gòu)體和聯(lián)合體的區(qū)別: ①結(jié)構(gòu)體和聯(lián)合體:都是由不同的數(shù)據(jù)類型成員組成,但是在同一時刻,聯(lián)合體只存放了一 個被選中的成員;而結(jié)構(gòu)體成員都存在(不同成員存放地址不同)。
②聯(lián)合體不同成員賦值,會對其他成員重寫,原來成員的值會不存在。 結(jié)構(gòu)體的不同成員賦值是互不影響的
補(bǔ)充:
各種指針的定義:
1.一個指向指針的指針,他指向的指針指向一個整型數(shù)? ? int **a;
2.一個有10個指針的數(shù)組,每個指針指向一個整型數(shù)? ? ? ?int *a[10];
3.一個指向10個整型數(shù)的數(shù)組的指針? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int (*a)[10];
4.一個指向指針的指針,被指向的指針指向一個有10個整型數(shù)的數(shù)組? ? ? ? ? int (**a)[10];
5.一個指向數(shù)組的指針,該數(shù)組有10個整型指針? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int *(*a)[10];
6.一個指向函數(shù)的指針,該函數(shù)有一個整型參數(shù)并返回一個整型數(shù)? ? ? ?int (*a)(int);
7.一個有10個指針的數(shù)組,每個指針指向一個函數(shù),該函數(shù)有一個整型參數(shù)并返回一個整型數(shù)? ?
int (*a[10])(int);
8.一個函數(shù)的指針,指向函數(shù)的類型是有兩個整型參數(shù)并且返回一個函數(shù)指針的函數(shù),返回的函數(shù)指針指向有一個整型參數(shù)并返回整型數(shù) 的函數(shù)? ? ? int (*(*a)(int,int))(int);
9.數(shù)組指針: int (*p)[4];
10.指針數(shù)組:int *p[4];
總結(jié)
- 上一篇: 彻底解决EMI问题,只需8秒
- 下一篇: mysql in 宕机_一条SQL引起的