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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C/C++经典面试题

發布時間:2023/12/9 c/c++ 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C/C++经典面试题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

面試題1:變量的聲明和定義有什么區別

為變量分配地址和存儲空間的稱為定義,不分配地址的稱為聲明。一個變量可以在多個地方聲明,但只能在一個地方定義。加入extern修飾的是變量的聲明,說明此變量將在文件以外或在文件后面部分定義。

說明:很多時候一個變量,只是聲明,不分配內存空間,知道具體使用時才初始化,分配內存空間,如外部變量。


面試題2:sizeof和strlen的區別

sizeof和strlen有以下區別:
? sizeof是一個操作符,strlen是庫函數。
? sizeof的參數可以是數據的類型,也可以是變量,而strlen只能以結尾為‘\0‘的字符串作參數。
? 編譯器在編譯時就計算出了sizeof的結果。而strlen函數必須在運行時才能計算出來。并且sizeof計算的是數據類型占內存的大小,而strlen計算的是字符串實際的長度。
? 數組做sizeof的參數不退化,傳遞給strlen就退化為指針了。
注意:有些是操作符看起來像是函數,而有些函數名看起來又像操作符,這類容易混淆的名稱一定要加以區分,否則遇到數組名這類特殊數據類型作參數時就很容易出錯。最容易混淆為函數的操作符就是sizeof。
說明:指針是一種普通的變量,從訪問上沒有什么不同于其他變量的特性。其保存的數值是個整型數據,和整型變量不同的是,這個整型數據指向的是一段內存地址。


面試題3:寫一個“標準”宏MIN

#define min(a,b) ((a)<=(b)?(a):(b))


面試題4:一個指針可以是volatile嗎?

可以,因為指針和普通變量一樣,有時也有變化程序的不可控性。常見例:子中斷服務子程序修改一個指向一個buffer的指針時,必須用volatile來修飾這個指針。


面試題5:a 和 &a 有什么區別

請寫出以下代碼的打印結果,主要目的是考察a和&a的區別。

[cpp]?view plaincopy
  • #include<stdio.h>???
  • void?main(?void?)???
  • {???
  • ?????int?a[5]={1,2,3,4,5};??
  • ?????int?*ptr=(int?*)(&a+1);??
  • ?????printf("%d,%d",*(a+1),*(ptr-1));???
  • ?????return;??
  • ?}??
  • 輸出結果:2,5。

    注意:數組名a可以作數組的首地址,而&a是數組的指針。思考,將原式的int *ptr=(int *)(&a+1);改為int *ptr=(int *)(a+1);時輸出結果將是什么呢?


    面試題6:簡述C、C++程序編譯的內存分配情況

    C、C++中內存分配方式可以分為三種:

    (1)從靜態存儲區域分配:
    內存在程序編譯時就已經分配好,這塊內存在程序的整個運行期間都存在。速度快、不容易出錯,因為有系統會善后。例如全局變量,static變量等。
    (2)在棧上分配:
    在執行函數時,函數內局部變量的存儲單元都在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。
    (3)從堆上分配:
    即動態內存分配。程序在運行的時候用malloc或new申請任意大小的內存,程序員自己負責在何時用free或delete釋放內存。動態內存的生存期由程序員決定,使用非常靈活。如果在堆上分配了空間,就有責任回收它,否則運行的程序會出現內存泄漏,另外頻繁地分配和釋放不同大小的堆空間將會產生堆內碎塊。
    一個C、C++程序編譯時內存分為5大存儲區:堆區、棧區、全局區、文字常量區、程序代碼區。


    面試題7:簡述strcpy sprintf與mencpy的區別

    三者主要有以下不同之處:
    (1)操作對象不同,strcpy的兩個操作對象均為字符串,sprintf的操作源對象可以是多種數據類型,目的操作對象是字符串,memcpy 的兩個對象就是兩個任意可操作的內存地址,并不限于何種數據類型。
    (2)執行效率不同,memcpy最高,strcpy次之,sprintf的效率最低。
    (3)實現功能不同,strcpy主要實現字符串變量間的拷貝,sprintf主要實現其他數據類型格式到字符串的轉化,memcpy主要是內存塊間的拷貝。
    說明:strcpy、sprintf與memcpy都可以實現拷貝的功能,但是針對的對象不同,根據實際需求,來選擇合適的函數實現拷貝功能。


    面試題8:鏈表與數組的區別

    數組和鏈表有以下幾點不同:
    (1)存儲形式:數組是一塊連續的空間,聲明時就要確定長度。鏈表是一塊可不連續的動態空間,長度可變,每個結點要保存相鄰結點指針。
    (2)數據查找:數組的線性查找速度快,查找操作直接使用偏移地址。鏈表需要按順序檢索結點,效率低。
    (3)數據插入或刪除:鏈表可以快速插入和刪除結點,而數組則可能需要大量數據移動。
    (4)越界問題:鏈表不存在越界問題,數組有越界問題。
    說明:在選擇數組或鏈表數據結構時,一定要根據實際需要進行選擇。數組便于查詢,鏈表便于插入刪除。數組節省空間但是長度固定,鏈表雖然變長但是占了更多的存儲空間。


    面試題9:簡述隊列和棧的異同

    隊列和棧都是線性存儲結構,但是兩者的插入和刪除數據的操作不同,隊列是“先進先出”,棧是“后進先出”。
    注意:區別棧區和堆區。堆區的存取是“順序隨意”,而棧區是“后進先出”。棧由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似于數據結構中的棧。堆一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收。分配方式類似于鏈表。
    它與本題中的堆和棧是兩回事。堆棧只是一種數據結構,而堆區和棧區是程序的不同內存存儲區域。


    面試題10:編碼實現直接插入排序

    直接插入排序編程實現如下:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • ??
  • int?main()??
  • {??
  • ????int?i,temp,p;??
  • ????int?array[10]?=?{2,6,1,9,4,7,5,8,3,0};??
  • ????printf("Display?this?array:\n");??
  • ????for(i=0;i<10;i++)??
  • ????{??
  • ????????printf("%d?",array[i]);??
  • ????}??
  • ??????
  • ????for(i=1;i<10;i++)??
  • ????{??
  • ????????temp?=?array[i];??
  • ????????p?=?i-1;??
  • ????????while(p?>=?0?&&?temp?<?array[p])??
  • ????????{??
  • ????????????array[p+1]?=?array[p];??
  • ????????????p--;??
  • ????????}??
  • ????????array[p+1]?=?temp;??
  • ????}??
  • ????printf("\n");??
  • ????printf("After?sorting,this?array?is:\n");??
  • ????for(i=0;i<10;i++)??
  • ????{??
  • ????????printf("%d?",array[i]);??
  • ????}?????
  • ????printf("\n");??
  • ????return?0;??
  • }??

  • 面試題11:編碼實現冒泡排序

    冒泡排序編程實現如下:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #define?LEN?10??
  • ??
  • int?main()??
  • {??
  • ????int?a,i,j;??
  • ????int?ARRAY[10]={23,1,4,9,6,17,24,56,98,72};??
  • ????printf("\n");??
  • ????printf("Display?this?array:\n");??
  • ????for(a=0;a<10;a++)??
  • ????{??
  • ????????printf("%d?",ARRAY[a]);??
  • ????}??
  • ????printf("\n");??
  • ????for(j=0;j<10;j++)??
  • ????{?????
  • ????????for(i=0;i<LEN-j-1;i++)??
  • ????????{??
  • ????????????int?temp;??
  • ????????????if(ARRAY[i]>ARRAY[i+1])??
  • ????????????{??
  • ????????????????temp=ARRAY[i+1];??
  • ????????????????ARRAY[i+1]=ARRAY[i];??
  • ????????????????ARRAY[i]=temp;??
  • ????????????}??
  • ????????}??
  • ????}??
  • ????printf("\nAfter?sorting,the?array?is:\n");??
  • ????for(a=0;a<LEN;a++)??
  • ????{??
  • ????????printf("%d?",ARRAY[a]);??
  • ????}??
  • ????printf("\n");??
  • ????return?0;?????
  • }??


  • 面試題12:編碼實現直接選擇排序

    選擇排序實現代碼如下:

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • ??
  • int?main()??
  • {??
  • ????int?i,j,t;??
  • ????int?array[10]={2,7,1,8,5,9,3,4,0,6};??
  • ????printf("\nDisplay?this?array:\n");??
  • ????for(i=0;i<10;i++)??
  • ????{??
  • ????????printf("%d?",array[i]);??
  • ????}??
  • ????printf("\n");??
  • ????for(i=1;i<=9;i++)??
  • ????{??
  • ????????int?t?=?i-1;??
  • ????????for(j=i;j<10;j++)??
  • ????????{??
  • ????????????if(array[j]<array[t])??
  • ????????????{??
  • ????????????????t=j;??
  • ????????????}??
  • ????????}??
  • ????????if(t!=(i-1))??
  • ????????{??
  • ????????????int?temp?=?0;??
  • ????????????temp=array[i-1];??
  • ????????????array[i-1]=array[t];??
  • ????????????array[t]=temp;??
  • ????????}??
  • ????}??
  • ????printf("After?sorting,this?array?is:\n");??
  • ????for(i=0;i<10;i++)??
  • ????{??
  • ????????printf("%d?",array[i]);??
  • ????}??
  • ????printf("\n");??
  • ????return?0;??
  • }??

  • 注:對比冒泡排序和選擇排序之間的區別

    區別在于:冒泡算法,每次比較如果發現較小的元素在后面,就交換兩個相鄰的元素。而選擇排序算法的改進在于:先并不急于調換位置,先從A[1]開始逐個檢查,看哪個數最小就記下該數所在的位置P,等一躺掃描完畢,再把A[P]和A[1]對調,這時A[1]到A[10]中最小的數據就換到了最前面的位置

    所以,選擇排序每掃描一遍數組,只需要一次真正的交換,而冒泡可能需要很多次。比較的次數是一樣的。


    面試題13:typedef和define有什么區別

    (1)用法不同:typedef用來定義一種數據類型的別名,增強程序的可讀性。define主要用來定義常量,以及書寫復雜使用頻繁的宏。
    (2)執行時間不同:typedef是編譯過程的一部分,有類型檢查的功能。define是宏定義,是預編譯的部分,其發生在編譯之前,只是簡單的進行字符串的替換,不進行類型的檢查。
    (3)作用域不同:typedef有作用域限定。define不受作用域約束,只要是在define聲明后的引用都是正確的。
    (4)對指針的操作不同:typedef和define定義的指針時有很大的區別。
    注意:typedef定義是語句,因為句尾要加上分號。而define不是語句,千萬不能在句尾加分號;


    面試題14:關鍵字const是什么

    const用來定義一個只讀的變量或對象。主要優點:便于類型檢查、同宏定義一樣可以方便地進行參數的修改和調整、節省空間,避免不必要的內存分配、可為函數重載提供參考。
    說明:const修飾函數參數,是一種編程規范的要求,便于閱讀,一看即知這個參數不能被改變,實現時不易出錯。


    面試題15:static有什么作用
    static在C中主要用于定義全局靜態變量、定義局部靜態變量、定義靜態函數。在C++中新增了兩種作用:定義靜態數據成員、靜態函數成員。
    注意:因為static定義的變量分配在靜態區,所以其定義的變量的默認值為0,普通變量的默認值為隨機數,在定義指針變量時要特別注意。


    面試題16:extern有什么作用

    extern標識的變量或者函數聲明其定義在別的文件中,提示編譯器遇到此變量和函數時在其它模塊中尋找其定義。


    面試題17:簡述指針常量與常量指針區別
    指針常量是指定義了一個指針,這個指針的值只能在定義時初始化,其他地方不能改變。其實指針常量是唯一的,即NULL;常量指針是指定義了一個指針,這個指針指向一個只讀的對象,不能通過常量指針來改變這個對象的值。
    指針常量強調的是指針的不可改變性,而常量指針強調的是指針對其所指對象的不可改變性。
    注意:無論是指針常量還是常量指針,其最大的用途就是作為函數的形式參數,保證實參在被調用函數中的不可改變特性。


    面試題18:如何避免“野指針”
    “野指針”產生原因及解決辦法如下:
    (1)指針變量聲明時沒有被初始化。解決辦法:指針聲明時初始化,可以是具體的地址值,也可讓它指向NULL。
    (2)指針 p 被 free 或者 delete 之后,沒有置為 NULL。解決辦法:指針指向的內存空間被釋放后指針應該指向NULL。
    (3)指針操作超越了變量的作用范圍。解決辦法:在變量的作用域結束前釋放掉變量的地址空間并且讓指針指向NULL。
    注意:“野指針”的解決方法也是編程規范的基本原則,平時使用指針時一定要避免產生“野指針”,在使用指針前一定要檢驗指針的合法性。


    面試題19:用C編寫一個死循環程序

    [cpp]?view plaincopy
  • while()??
  • {??
  • }??
  • 其實還有

    [cpp]?view plaincopy
  • for(;;)??
  • 說明:很多種途徑都可實現同一種功能,但是不同的方法時間和空間占用度不同,特別是對于嵌入式軟件,處理器速度比較慢,存儲空間較小,所以時間和空間優勢是選擇各種方法的首要考慮條件。

    面試題20:編碼實現某一變量某位清0或置1

    給定一個整型變量a,寫兩段代碼,第一個設置a的bit 3,第二個清a的bit 3,在以上兩個操作中,要保持其他位不變。

    筆者認為,在對ARM寄存器操作時會經常用到這一塊,所以要注意這塊:

    [cpp]?view plaincopy
  • #define?BIT3?(0x1?<<?3?)?Satic?int?a;??
  • //設置a的bit?3:???
  • void?set_bit3(?void?)???
  • {???
  • ??????a?|=?BIT3;?//將a第3位置1???
  • }??
  • //清a的bit?3???
  • void?set_bit3(?void?)???
  • {??
  • ????a?&=?~BIT3;?//將a第3位清零???
  • }??
  • 說明:在置或清變量或寄存器的某一位時,一定要注意不要影響其他位。所以用加減法是很難實現的。

    還有一個就是保留某位:

    [cpp]?view plaincopy
  • //保留第k位??
  • void?set_bit3(void)??
  • {??
  • ????a?&=?BIT3;??
  • }??

  • ?

    面試題21:a=3,b=5,不用第三變量temp,對a和b的值進行交換

    如果有第三者temp,a和b交換非常方便:

    [cpp]?view plaincopy
  • temp?=?a;??
  • a?=?b;??
  • b?=temp;??
  • 若無temp,可以這樣做:

    a = a + b;

    b = a - b;

    a = a - b;

    當然,我們可以利用C語言的位運算符:

    [cpp]?view plaincopy
  • a?=?3;b?=?5;??
  • a?^=?b;??
  • b?^=?a;??
  • a?^=?b;??
  • 原理是a ^ b ^ b == a; a ^ b == b ^ a;



    面試題22:宏定義的用法,看下面這個程序,求出結果

    [cpp]?view plaincopy
  • #include?<stdio.h>??
  • #define?S(a,b)?a*b??
  • ??
  • int?main(void)??
  • {??
  • int?n?=?3;??
  • int?m?=?5;??
  • printf("%d",S(n+m,m+n));??
  • ??
  • return?0;??
  • }??
  • 這道題容易出現的錯誤結果是64,得到這個結果肯定是這樣理解的(3+5)*(5+3)。其實并不是,大家要理解宏定義的概念,宏定義只是簡單的符號替換,而不做其他處理,所以這里得到的結果是 3+5*5+3=31.

    大家看看運行結果:

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/hanshu$?gcc?-o?1?1.c??
  • fs@ubuntu:~/qiang/hanshu$?./1??
  • 31??
  • 要想得到正確結果,應該怎么樣呢?應該這樣改,define s(a,b) (a)*(b),這樣才是正確結果;

    [cpp]?view plaincopy
  • fs@ubuntu:~/qiang/hanshu$?gcc?-o?1?1.c??
  • fs@ubuntu:~/qiang/hanshu$?./1??
  • 64??
  • 大家記住這句話,宏定義只是簡單的符號替換!


    面試題23:

    C語言中,運算對象必須是整型數的運算符的有()

    A、%????? B、/????? C、%和/????? D、*

    答案:A

    取余對象必須是整數型


    面試題25:

    以下程序執行的結果是__

    [cpp]?view plaincopy
  • #include?<stdio.h>]??
  • #define?N??2??
  • #define?M??N+1??
  • #define?NUM??(M+1)*M/2??
  • main()??
  • {??
  • pritf("%d",NUM);??
  • }??
  • A、5?? B、6? C、8?? D、9

    答案:C

    注意宏定義的使用,此處NUM = (3+1)*2+1/2 為8

    總結

    以上是生活随笔為你收集整理的C/C++经典面试题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。