日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

C语言面试题汇总(持续更)「建议收藏」

發(fā)布時(shí)間:2023/12/19 综合教程 22 生活家
生活随笔 收集整理的這篇文章主要介紹了 C语言面试题汇总(持续更)「建议收藏」 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

筆者最近在找工作,因此對(duì)應(yīng)聘C/C++嵌入式開發(fā)工程師容易被問到,或者經(jīng)常搞不清楚的問題做一個(gè)匯總,也希望能對(duì)找工作的小伙伴起到幫助參考的作用。本篇集中于C語言方面的面試題目。

因?yàn)槭亲约嚎偨Y(jié)的,可能會(huì)存在錯(cuò)誤,還煩請(qǐng)各位讀者批評(píng)指正。


一、變量?jī)?nèi)存分配

1.一個(gè)由C/C++編譯的程序占用的內(nèi)存分為以下幾個(gè)部分:

①棧區(qū) —— 局部變量 —— 向低地址生長(zhǎng) —— 自動(dòng)釋放 ——其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。

②堆區(qū)—— 向高地址生長(zhǎng) —— 手動(dòng)分配、釋放的存儲(chǔ)區(qū) —— malloc,free——它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式倒是類似于鏈表

③全局/靜態(tài)存儲(chǔ)區(qū)static—— 全局變量,靜態(tài)變量,程序運(yùn)行結(jié)束后自動(dòng)釋放

④常量存儲(chǔ)區(qū)const —— 常量字符串儲(chǔ)存在這里。儲(chǔ)存在常量區(qū)的只讀不可寫。程序運(yùn)行結(jié)束后自動(dòng)釋放

⑤代碼區(qū) ——存放函數(shù)體的二進(jìn)制代碼。

  • 靜態(tài)內(nèi)存分配:編譯時(shí)分配,包括:全局、靜態(tài)全局、靜態(tài)局部
  • 動(dòng)態(tài)內(nèi)存分配:運(yùn)行時(shí)分配:包括:棧(局部變量),堆(C語言常用到的變量被動(dòng)態(tài)地分配到內(nèi)存當(dāng)中:malloc,calloc,realloc,free函數(shù))

——> const修飾的全局變量也儲(chǔ)存在常量區(qū);

——> const修飾的局部變量依然在上。

int a = 0; //全局初始化區(qū) 
char *p1; //全局未初始化區(qū) 
main() 
{ 
int b; //棧 
char s[] = "abc"; //棧 
char *p2; //棧 
char *p3 = "123456"; //123456
int a = 0; //全局初始化區(qū) 
char *p1; //全局未初始化區(qū) 
main() 
{ 
int b; //棧 
char s[] = "abc"; //棧 
char *p2; //棧 
char *p3 = "123456"; //123456\0在常量區(qū),p3在棧上。 
static int c =0; //全局(靜態(tài))初始化區(qū) 
p1 = (char *)malloc(10); 
p2 = (char *)malloc(20); //分配得來得10和20字節(jié)的區(qū)域就在堆區(qū)。 
strcpy(p1, "123456"); //123456\0放在常量區(qū),編譯器可能會(huì)將它與p3所指向的"123456"優(yōu)化成一個(gè)地方。 
}

在常量區(qū),p3在棧上。
static int c =0; //全局(靜態(tài))初始化區(qū)
p1 = (char *)malloc(10);
p2 = (char *)malloc(20); //分配得來得10和20字節(jié)的區(qū)域就在堆區(qū)。
strcpy(p1, "123456"); //123456

int a = 0; //全局初始化區(qū) 
char *p1; //全局未初始化區(qū) 
main() 
{ 
int b; //棧 
char s[] = "abc"; //棧 
char *p2; //棧 
char *p3 = "123456"; //123456\0在常量區(qū),p3在棧上。 
static int c =0; //全局(靜態(tài))初始化區(qū) 
p1 = (char *)malloc(10); 
p2 = (char *)malloc(20); //分配得來得10和20字節(jié)的區(qū)域就在堆區(qū)。 
strcpy(p1, "123456"); //123456\0放在常量區(qū),編譯器可能會(huì)將它與p3所指向的"123456"優(yōu)化成一個(gè)地方。 
}

放在常量區(qū),編譯器可能會(huì)將它與p3所指向的"123456"優(yōu)化成一個(gè)地方。
}

2. 存儲(chǔ)類(內(nèi)存管理):

①棧:局部變量,函數(shù)調(diào)用傳參的過程。
②堆:動(dòng)態(tài)存儲(chǔ)區(qū),需要程序員去申請(qǐng)釋放
③數(shù)據(jù)段(data段):顯式初始化僅非零的全局變量

3.static修飾的變量

(1)static修飾局部變量(靜態(tài)局部變量)與普通局部變量相比:
① 靜態(tài)局部變量作用域與連接屬性,和普通局部變量一樣
② 存儲(chǔ)類:靜態(tài)局部變量分配在data/bss段,普通局部變量在棧上
③ 生命周期:因?yàn)榇鎯?chǔ)類的不同,靜態(tài)局部變量生命周期變長(zhǎng)了,直到程序結(jié)束

——所以當(dāng)靜態(tài)局部變量離開作用域后,并沒有銷毀,而是仍然駐留在內(nèi)存當(dāng)中,只不過我們不能夠再對(duì)它進(jìn)行訪問,直到該函數(shù)被再次調(diào)用,并且值不變。

(2)static修飾的全局變量or函數(shù)與普通的相比:
① 存儲(chǔ)類、生命周期、作用域都一樣
② 差別在于:
static修飾的全局變量的連接屬性是內(nèi)連接,普通的是外連接
即:static修飾的全局變量不能給文件調(diào)用——這也是靜態(tài)變量和全局變量的區(qū)別。

對(duì)于局部變量來說,聲明存儲(chǔ)類型的作用是指定變量存儲(chǔ)的區(qū)域(靜態(tài)存儲(chǔ)區(qū)或動(dòng)態(tài)存儲(chǔ)區(qū))以及由此產(chǎn)生的生存期的問題

對(duì)于全局變量來說,由于都是在編譯時(shí)分配內(nèi)存,都存放在靜態(tài)存儲(chǔ)區(qū),聲明存儲(chǔ)類型的作用是變量作用域的擴(kuò)展問題。

4. 其他

1. 變量類型:是對(duì)數(shù)據(jù)分配存儲(chǔ)單元的安排,包括存儲(chǔ)單元的長(zhǎng)度,及數(shù)據(jù)的存儲(chǔ)形式

2. 內(nèi)部函數(shù):只能被本文件中的其他函數(shù)調(diào)用。定義內(nèi)部函數(shù)時(shí),在函數(shù)名、函數(shù)類型前加static。

外部函數(shù):可供其他文件調(diào)用。定義外部函數(shù)時(shí),在函數(shù)首部左端加上extern。若定義函數(shù)時(shí)省略extern,則默認(rèn)為外部函數(shù)。

3. 因?yàn)锳、B、C是外部變量

所以調(diào)用max函數(shù)時(shí)用不到參數(shù)傳遞,即在max函數(shù)中可以直接使用外部變量A、B、C的值

(這一點(diǎn)與局部變量有個(gè)實(shí)參傳給形參的過程不同)

二、堆和棧有什么區(qū)別?(為什么又是這個(gè))

1、堆??臻g分配區(qū)別

棧(操作系統(tǒng)):由操作系統(tǒng)(編譯器)自動(dòng)分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。

堆(操作系統(tǒng)): 一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由OS回收,分配方式倒是類似于鏈表。

2、堆棧緩存方式區(qū)別

棧使用的是一級(jí)緩存, 它們通常都是被調(diào)用時(shí)處于存儲(chǔ)空間中,調(diào)用完畢立即釋放。

堆則是存放在二級(jí)緩存中,生命周期由虛擬機(jī)的垃圾回收算法來決定(并不是一旦成為孤兒對(duì)象就能被回收)。所以調(diào)用這些對(duì)象的速度要相對(duì)來得低一些。

3、堆棧數(shù)據(jù)結(jié)構(gòu)區(qū)別

堆(數(shù)據(jù)結(jié)構(gòu)):堆可以被看成是一棵樹,如:堆排序。

棧(數(shù)據(jù)結(jié)構(gòu)):一種先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)。

三、數(shù)據(jù)結(jié)構(gòu)集中問題

1. 串值的存儲(chǔ)空間可在程序執(zhí)行過程中動(dòng)態(tài)分配而得。

2. 根結(jié)點(diǎn)是沒有雙親的,所以我們約定根結(jié)點(diǎn)的位置域?yàn)?1.

3. 鏈表翻轉(zhuǎn)(迭代法)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* reverseList(struct ListNode* head){
    if (head == NULL || head->next == NULL)
        return head;
    
    struct ListNode *pre = head;
    struct ListNode *cur = head->next;
    struct ListNode *tmp = head->next->next;
    
    while(cur)
    {
        tmp = cur->next; //當(dāng)前位置的下一個(gè)的值給tmp先存著
        cur->next = pre; //把上一個(gè)位置的值給下一個(gè)
        pre = cur;//把當(dāng)前位置的值給上一個(gè)
        cur = tmp;//把之前下一個(gè)的值給當(dāng)前位置
    }
    head->next = NULL;
    
    return pre;

}

四、指針

1. *在不同的場(chǎng)景下有不同的作用

*可以用在指針變量的定義中,表明這是一個(gè)指針變量,以和普通變量區(qū)分開;

*也可以在使用指針變量時(shí),在變量前面加上,表示獲取指針指向的數(shù)據(jù),或者說表示的是指針指向的數(shù)據(jù)本身。

也就是說,定義指針變量時(shí)的*使用指針變量時(shí)的*意義完全不同。以下面的語句為

  1. int *p = &a;
    *p = 100;

第1行代碼中*用來指明 p 是一個(gè)指針變量,第2行代碼中*用來獲取指針指向的數(shù)據(jù)。

需要注意的是,給指針變量本身賦值時(shí)不能加*。修改上面的語句:

int *p;
p = &a;
*p = 100;

第2行代碼中的 p 前面就不能加*。

指針變量也可以出現(xiàn)在普通變量能出現(xiàn)的任何表達(dá)式中,例如:

int x, y, *px = &x, *py = &y;
y = *px + 5;  //表示把x的內(nèi)容加5并賦給y,*px+5相當(dāng)于(*px)+5
y = ++*px;  //px的內(nèi)容加上1之后賦給y,++*px相當(dāng)于++(*px)
y = *px++;  //相當(dāng)于y=(*px)++
py = px;  //把一個(gè)指針的值賦給另一個(gè)指針

2. 如果已執(zhí)行“p=&a;”,即指針變量p指向了整型變量a,則:

printf("%d",*p);

其作用是:以整數(shù)形式輸出指針變量p所指向的變量的值,即變量a的值。

3. 當(dāng)數(shù)組作為函數(shù)的參數(shù)傳遞時(shí),數(shù)組就自動(dòng)退化為同類型指針。

五、雜項(xiàng)

1. const和define的區(qū)別

1.數(shù)據(jù)類型:const修飾的變量有明確的類型,而宏沒有明確的數(shù)據(jù)類型

2.安全方面:const修飾的變量會(huì)被編譯器檢查,而宏沒有安全檢查

3.內(nèi)存分配:const修飾的變量只會(huì)在第一次賦值時(shí)分配內(nèi)存,而宏是直接替換,每次替換后的變量都會(huì)分配內(nèi)存

4.作用場(chǎng)所:const修飾的變量作用在編譯、運(yùn)行的過程中,而宏作用在預(yù)編譯中

5.代碼調(diào)試:const方便調(diào)試,而宏在預(yù)編譯中進(jìn)行所以沒有辦法進(jìn)行調(diào)試。

—— const關(guān)鍵字的作用:

1. const 是定義只讀變量的關(guān)鍵字,或者說 const 是定義常變量的關(guān)鍵字。
說 const 定義的是變量,但又相當(dāng)于常量;說它定義的是常量,但又有變量的屬性,所以叫常變量。用 const 定義常變量的方法很簡(jiǎn)單,就在通常定義變量時(shí)前面加 const 即可,如:

const  int  a = 10;

const 和變量類型 int 可以互換位置,二者是等價(jià)的,即上條語句等價(jià)于:

int  const  a = 10;

那么用 const 修飾后和未修飾前有什么區(qū)別呢?它們不都等于 10 嗎?、

  • 用 const 定義的變量的值是不允許改變的,即不允許給它重新賦值,即使是賦相同的值也不可以。所以說它定義的是只讀變量。這也就意味著必須在定義的時(shí)候就給它賦出值。
  • 如果定義的時(shí)候未初始化,我們知道,對(duì)于未初始化的局部變量,程序在執(zhí)行的時(shí)候會(huì)自動(dòng)把一個(gè)很小的負(fù)數(shù)存放進(jìn)去。這樣后面再給它賦出值的話就是“改變它的值”了,即發(fā)生語法錯(cuò)誤。

2.

const int * p1 = &i; //p1指向的值不能改變

int * const p2 =&j; //p2本身的值(即指向的值的地址)不能改變

上面定義了兩個(gè)指針p1和p2。

在定義1中const限定的是*p1,即其指向空間的值不可改變,若改變其指向空間的值如*p1=20,則程序會(huì)報(bào)錯(cuò);但p1的值是可以改變的,對(duì)p1重新賦值如p1=&k是沒有任何問題的。

在定義2中const限定的是指針p2,若改變p2的值如p2=&k,程序?qū)?huì)報(bào)錯(cuò);但*p2,即其所指向的值可以改變,如*p2=80是沒有問題的,程序正常執(zhí)行。

const常量會(huì)在內(nèi)存中分配??

2. ifndef – endif 的作用:避免重定義

3. 參數(shù)傳遞:

三種參數(shù)傳遞的方式:傳值、傳指針、傳引用

形參的存儲(chǔ)空間是函數(shù)被調(diào)用時(shí)才分配的

  • 引用是別名,指針是地址(實(shí)體)

引用一旦與某個(gè)對(duì)象綁定后就不再改變了

string str1 = "a";
string str3 = "b";
string &str2 = str1; //str2指向str1的地址
str2 = str3;

4. malloc和calloc

malloc:分配n個(gè)字節(jié) calloc:分配n*size個(gè)字節(jié)

5.進(jìn)程和線程的區(qū)別?

進(jìn)程:是執(zhí)行中一段程序,即一旦程序被載入到內(nèi)存中并準(zhǔn)備執(zhí)行,它就是一個(gè)進(jìn)程。進(jìn)程是表示資源分配的的基本概念,又是調(diào)度運(yùn)行的基本單位,是系統(tǒng)中的并發(fā)執(zhí)行的單位。

線程:單個(gè)進(jìn)程中執(zhí)行中每個(gè)任務(wù)就是一個(gè)線程。線程是進(jìn)程中執(zhí)行運(yùn)算的最小單位。

一個(gè)線程只能屬于一個(gè)進(jìn)程,但是一個(gè)進(jìn)程可以擁有多個(gè)線程。多線程處理就是允許一個(gè)進(jìn)程中在同一時(shí)刻執(zhí)行多個(gè)任務(wù)。

6.#include <> 和 #include” “

老生常談的問題。

#include <> :到保存系統(tǒng)標(biāo)準(zhǔn)頭文件的位置查找頭文件。

#include” “:查找當(dāng)前目錄是否有指定名稱的頭文件,然后再從標(biāo)準(zhǔn)頭文件目錄中查找。

7.遞歸

每個(gè)遞歸必須至少有一個(gè)條件,其滿足時(shí)遞歸便不再運(yùn)行,即:此時(shí)不再引用自身,而是返回值退出。

for (i=2;i<40;i++)
     a[i]=a[i-1]+a[i-2];

int Fbi(int i){
    return Fbi(i-1)+Fbi(i-2);
}

8. 輸入逗號(hào)

使用 scanf(“%d%d%d”,&a,&b,&c);從鍵盤中獲得任意 3 個(gè)數(shù)。在輸入數(shù)據(jù)時(shí),在兩個(gè)數(shù)據(jù)之間以一個(gè)或多個(gè)空格間隔,也可以用 Enter 健、Tab 鍵,不能用逗號(hào)作為兩個(gè)數(shù)據(jù)間的分隔符。

如果用格式輸入函數(shù) scanf(“%d,%d,%d”,&a,&b,&c) 輸入數(shù)據(jù),兩個(gè)數(shù)據(jù)之間要用“,”做間隔。

9. 各種數(shù)據(jù)類型的長(zhǎng)度

1. signed char取值范圍bai是 -128 到 127 ——一個(gè)字節(jié),2的8次方
unsigned char 取值范圍是 0 到 255

2. 一個(gè)int占4個(gè)字節(jié),sizeof就是4。在32位系統(tǒng)上,對(duì)任意指針求sizeof得到的結(jié)果都是4.??

10. 輸出

printf("x1=%7.2f\nx2=%7.2f\n",x1,x2);

x1=%7.2f

7.2是指:寬度占7個(gè),精確到小數(shù)點(diǎn)后兩位(輸出數(shù)據(jù)占7列,其中小數(shù)占2列)

x1=  -1.00
x2=  -2.00

NULL==ptr

free()

FreeRTOS任務(wù)調(diào)度方式

二分 哈希

pa、pb、pc 每次加 1,它們的地址分別增加 4、8、1,正好是 int、double、char 類型的長(zhǎng)度;減 2 時(shí),地址分別減少 8、16、2,正好是 int、double、char 類型長(zhǎng)度的 2 倍。

887

1.左邊界:只需要考慮相鄰右元素是否存在坑

2.右邊界:只需要考慮相鄰左元素是否存在坑

3.中間:考慮相鄰兩邊元素是否存在坑

總結(jié)

以上是生活随笔為你收集整理的C语言面试题汇总(持续更)「建议收藏」的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。