自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

嵌入式筆試面試題目系列(二)

開發(fā) 前端
本系列將按類別對題目進行分類整理,重要的地方標(biāo)上星星,這樣有利于大家打下堅實的基礎(chǔ)。

[[376053]]

、前言

 本系列將按類別對題目進行分類整理,重要的地方標(biāo)上星星,這樣有利于大家打下堅實的基礎(chǔ)。

本文比較深入,需要花時間去理解,保證都是必考題。文章較長,可以先收藏,找個大塊時間看。一遍看不懂可以多看幾遍。

下面分享16個重要知識點。

二、C/C++題目

1、new和malloc

做嵌入式,對于內(nèi)存是十分在意的,因為可用內(nèi)存有限,所以嵌入式筆試面試題目,內(nèi)存的題目高頻。

1)malloc和free是c++/c語言的庫函數(shù),需要頭文件支持stdlib.h;new和delete是C++的關(guān)鍵字,不需要頭文件,需要編譯器支持;

2)使用new操作符申請內(nèi)存分配時,無需指定內(nèi)存塊的大小,編譯器會根據(jù)類型信息自行計算。而malloc則需要顯式地支持所需內(nèi)存的大小。

3)new操作符內(nèi)存分配成功時,返回的是對象類型的指針,類型嚴格與對象匹配,無需進行類型轉(zhuǎn)換,故new是符合類型安全性的操作符。而malloc內(nèi)存分配成功則是返回void*,需要通過強制類型轉(zhuǎn)換將void*指針轉(zhuǎn)換成我們需要的類型。

4)new內(nèi)存分配失敗時,會拋出bad_alloc異常。malloc分配內(nèi)存失敗時返回NULL。

2、在1G內(nèi)存的計算機中能否malloc(1.2G)?為什么?(2021浙江大華二面問題)

答:是有可能申請1.2G的內(nèi)存的。

解析:回答這個問題前需要知道m(xù)alloc的作用和原理,應(yīng)用程序通過malloc函數(shù)可以向程序的虛擬空間申請一塊虛擬地址空間,與物理內(nèi)存沒有直接關(guān)系,得到的是在虛擬地址空間中的地址,之后程序運行所提供的物理內(nèi)存是由操作系統(tǒng)完成的。

3 、extern”C” 的作用

我們可以在C++中使用C的已編譯好的函數(shù)模塊,這時候就需要用到extern”C”。也就是extern“C” 都是在c++文件里添加的。

extern在鏈接階段起作用(四大階段:預(yù)處理--編譯--匯編--鏈接)。

4、strcat、strncat、strcmp、strcpy哪些函數(shù)會導(dǎo)致內(nèi)存溢出?如何改進?(2021浙江大華二面問題)

strcpy函數(shù)會導(dǎo)致內(nèi)存溢出。

strcpy拷貝函數(shù)不安全,他不做任何的檢查措施,也不判斷拷貝大小,不判斷目的地址內(nèi)存是否夠用。

  1. char *strcpy(char *strDest,const char *strSrc) 

strncpy拷貝函數(shù),雖然計算了復(fù)制的大小,但是也不安全,沒有檢查目標(biāo)的邊界。

  1. strncpy(dest, src, sizeof(dest));  

strncpy_s是安全的

strcmp(str1,str2),是比較函數(shù),若str1=str2,則返回零;若str1

strncat()主要功能是在字符串的結(jié)尾追加n個字符。

  1. char * strncat(char *dest, const char *src, size_t n); 

strcat()函數(shù)主要用來將兩個char類型連接。例如:

  1. char d[20]="Golden"
  2. char s[20]="View"
  3. strcat(d,s); 
  4. //打印d 
  5. printf("%s",d); 

輸出 d 為 GoldenView (中間無空格)

延伸:

memcpy拷貝函數(shù),它與strcpy的區(qū)別就是memcpy可以拷貝任意類型的數(shù)據(jù),strcpy只能拷貝字符串類型。

memcpy 函數(shù)用于把資源內(nèi)存(src所指向的內(nèi)存區(qū)域)拷貝到目標(biāo)內(nèi)存(dest所指向的內(nèi)存區(qū)域);有一個size變量控制拷貝的字節(jié)數(shù);

函數(shù)原型:

  1. void *memcpy(void *dest, void *src, unsigned int count); 

5 、static的用法(定義和用途)(必考)

1)用static修飾局部變量:使其變?yōu)殪o態(tài)存儲方式(靜態(tài)數(shù)據(jù)區(qū)),那么這個局部變量在函數(shù)執(zhí)行完成之后不會被釋放,而是繼續(xù)保留在內(nèi)存中。

2)用static修飾全局變量:使其只在本文件內(nèi)部有效,而其他文件不可連接或引用該變量。

3)用static修飾函數(shù):對函數(shù)的連接方式產(chǎn)生影響,使得函數(shù)只在本文件內(nèi)部有效,對其他文件是不可見的(這一點在大工程中很重要很重要,避免很多麻煩,很常見)。這樣的函數(shù)又叫作靜態(tài)函數(shù)。使用靜態(tài)函數(shù)的好處是,不用擔(dān)心與其他文件的同名函數(shù)產(chǎn)生干擾,另外也是對函數(shù)本身的一種保護機制。

6、const的用法(定義和用途)(必考)

const主要用來修飾變量、函數(shù)形參和類成員函數(shù):

1)用const修飾常量:定義時就初始化,以后不能更改。

2)用const修飾形參:func(const int a){};該形參在函數(shù)里不能改變

3)用const修飾類成員函數(shù):該函數(shù)對成員變量只能進行只讀操作,就是const類成員函數(shù)是不能修改成員變量的數(shù)值的。

被const修飾的東西都受到強制保護,可以預(yù)防意外的變動,能提高程序的健壯性。

參考一個大佬的回答:

我只要一聽到被面試者說:"const意味著常數(shù)",我就知道我正在和一個業(yè)余者打交道。去年Dan Saks已經(jīng)在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應(yīng)該非常熟悉const能做什么和不能做什么.如果你從沒有讀到那篇文章,只要能說出const意味著"只讀"就可以了。盡管這個答案不是完全的答案,但我接受它作為一個正確的答案。如果應(yīng)試者能正確回答這個問題,我將問他一個附加的問題:下面的聲明都是什么意思?

  1. const int a; 
  2. int const a; 
  3. const int *a; 
  4. int * const a; 
  5. int const * a const; 

前兩個的作用是一樣,a是一個常整型數(shù)。

第三個意味著a是一個指向常整型數(shù)的指針(也就是,整型數(shù)是不可修改的,但指針可以)。

第四個意思a是一個指向整型數(shù)的常指針(也就是說,指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。

最后一個意味著a是一個指向常整型數(shù)的常指針(也就是說,指針指向的整型數(shù)是不可修改的,同時指針也是不可修改的)。

7、volatile作用和用法

一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設(shè)這個變量的值了。精確地說就是,優(yōu)化器在用到這個變量時必須每次都小心地重新讀取這個變量在內(nèi)存中的值,而不是使用保存在寄存器里的備份(雖然讀寫寄存器比讀寫內(nèi)存快)。

回答不出這個問題的人是不會被雇傭的。這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問題。搞嵌入式的家伙們經(jīng)常同硬件、中斷、RTOS等等打交道,所有這些都要求用到volatile變量。不懂得volatile的內(nèi)容將會帶來災(zāi)難。

以下幾種情況都會用到volatile:

1、并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)2、一個中斷服務(wù)子程序中會訪問到的非自動變量3、多線程應(yīng)用中被幾個任務(wù)共享的變量

8、const常量和#define的區(qū)別(編譯階段、安全性、內(nèi)存占用等)

用#define max 100 ; 定義的常量是沒有類型的(不進行類型安全檢查,可能會產(chǎn)生意想不到的錯誤),所給出的是一個立即數(shù),編譯器只是把所定義的常量值與所定義的常量的名字聯(lián)系起來,define所定義的宏變量在預(yù)處理階段的時候進行替換,在程序中使用到該常量的地方都要進行拷貝替換;

用const int max = 255 ; 定義的常量有類型(編譯時會進行類型檢查)名字,存放在內(nèi)存的靜態(tài)區(qū)域中,在編譯時確定其值。在程序運行過程中const變量只有一個拷貝,而#define所定義的宏變量卻有多個拷貝,所以宏定義在程序運行過程中所消耗的內(nèi)存要比const變量的大得多

9、變量的作用域(全局變量和局部變量)

全局變量:在所有函數(shù)體的外部定義的,程序的所在部分(甚至其它文件中的代碼)都可以使用。全局變量不受作用域的影響(也就是說,全局變量的生命期一直到程序的結(jié)束)。

局部變量:出現(xiàn)在一個作用域內(nèi),它們是局限于一個函數(shù)的。局部變量經(jīng)常被稱為自動變量,因為它們在進入作用域時自動生成,離開作用域時自動消失。關(guān)鍵字auto可以顯式地說明這個問題,但是局部變量默認為auto,所以沒有必要聲明為auto。

局部變量可以和全局變量重名,在局部變量作用域范圍內(nèi),全局變量失效,采用的是局部變量的值。

10、sizeof 與strlen (字符串,數(shù)組)

1.如果是數(shù)組

  1. #include<stdio.h> 
  2. int main() 
  3.     int a[5]={1,2,3,4,5}; 
  4.     printf(“sizeof  數(shù)組名=%d\n”,sizeof(a)); 
  5.     printf(“sizeof *數(shù)組名=%d\n”,sizeof(*a)); 

運行結(jié)果

  1. sizeof  數(shù)組名=20 
  2. sizeof *數(shù)組名=4 

2.如果是指針,sizeof只會檢測到是指針的類型,指針都是占用4個字節(jié)的空間(32位機)。

sizeof是什么?是一個操作符,也是關(guān)鍵字,就不是一個函數(shù),這和strlen()不同,strlen()是一個函數(shù)。

那么sizeof的作用是什么?返回一個對象或者類型所占的內(nèi)存字節(jié)數(shù)。我們會對sizeof()中的數(shù)據(jù)或者指針做運算嗎?基本不會。例如sizeof(1+2.0),直接檢測到其中類型是double,即是sizeof(double) = 8。如果是指針,sizeof只會檢測到是指針的類型,指針都是占用4個字節(jié)的空間(32位機)。

  1. char *p = "sadasdasd"
  2. sizeof(p):4 
  3. sizeof(*p):1//指向一個char類型的 

除非使用strlen(),僅對字符串有效,直到'\0'為止了,計數(shù)結(jié)果不包括\0。

要是非要使用sizeof來得到指向內(nèi)容的大小,就得使用數(shù)組名才行, 如

  1. char a[10]; 
  2. sizeof(a):10  //檢測到a是一個數(shù)組的類型。 

 

關(guān)于strlen(),它是一個函數(shù),考察的比較簡單:

  1. strlen “\n\t\tag\AAtang” 

答案:11

11、經(jīng)典的sizeof(struct)和sizeof(union)內(nèi)存對齊

內(nèi)存對齊作用:

1.平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。

2.性能原因:數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問;而對齊的內(nèi)存訪問僅需要一次訪問。

結(jié)構(gòu)體struct內(nèi)存對齊的3大規(guī)則:

1.對于結(jié)構(gòu)體的各個成員,第一個成員的偏移量是0,排列在后面的成員其當(dāng)前偏移量必須是當(dāng)前成員類型的整數(shù)倍;

2.結(jié)構(gòu)體內(nèi)所有數(shù)據(jù)成員各自內(nèi)存對齊后,結(jié)構(gòu)體本身還要進行一次內(nèi)存對齊,保證整個結(jié)構(gòu)體占用內(nèi)存大小是結(jié)構(gòu)體內(nèi)最大數(shù)據(jù)成員的最小整數(shù)倍;

3.如程序中有#pragma pack(n)預(yù)編譯指令,則所有成員對齊以n字節(jié)為準(zhǔn)(即偏移量是n的整數(shù)倍),不再考慮當(dāng)前類型以及最大結(jié)構(gòu)體內(nèi)類型。

  1. #pragma pack(1) 
  2.   
  3. struct fun{ 
  4.   int i; 
  5.   double d; 
  6.   char c; 
  7. }; 

sizeof(fun) = 13

  1. struct CAT_s 
  2.     int ld; 
  3.     char Color; 
  4.     unsigned short Age; 
  5.     char *Name
  6.     void(*Jump)(void); 
  7. }Garfield; 

1.使用32位編譯,int占4, char 占1, unsigned short 占2,char* 占4,函數(shù)指針占4個,由于是32位編譯是4字節(jié)對齊,所以該結(jié)構(gòu)體占16個字節(jié)。(說明:按幾字節(jié)對齊,是根據(jù)結(jié)構(gòu)體的最長類型決定的,這里是int是最長的字節(jié),所以按4字節(jié)對齊);

2.使用64位編譯 ,int占4, char 占1, unsigned short 占2,char* 占8,函數(shù)指針占8個,由于是64位編譯是8字節(jié)對齊(說明:按幾字節(jié)對齊,是根據(jù)結(jié)構(gòu)體的最長類型決定的,這里是函數(shù)指針是最長的字節(jié),所以按8字節(jié)對齊)所以該結(jié)構(gòu)體占24個字節(jié)。

  1. //64位 
  2. struct C  
  3. {  
  4.  double t;   //8   1111 1111 
  5.  char b;  //1      1 
  6.  int a;   //4      0001111   
  7.  short c;  //2     11000000 
  8. };   
  9.  sizeof(C) = 24;  //注意:1 4 2 不能拼在一起 

char是1,然后在int之前,地址偏移量得是4的倍數(shù),所以char后面補三個字節(jié),也就是char占了4個字節(jié),然后int四個字節(jié),最后是short,只占兩個字節(jié),但是總的偏移量得是double的倍數(shù),也就是8的倍數(shù),所以short后面補六個字節(jié)

聯(lián)合體union內(nèi)存對齊的2大規(guī)則:

1.找到占用字節(jié)最多的成員;

2.union的字節(jié)數(shù)必須是占用字節(jié)最多的成員的字節(jié)的倍數(shù),而且需要能夠容納其他的成員

  1. //x64 
  2. typedef union { 
  3.     long i; 
  4.     int k[5]; 
  5.     char c; 
  6. }D 

要計算union的大小,首先要找到占用字節(jié)最多的成員,本例中是long,占用8個字節(jié),int k[5]中都是int類型,仍然是占用4個字節(jié)的,然后union的字節(jié)數(shù)必須是占用字節(jié)最多的成員的字節(jié)的倍數(shù),而且需要能夠容納其他的成員,為了要容納k(20個字節(jié)),就必須要保證是8的倍數(shù)的同時還要大于20個字節(jié),所以是24個字節(jié)。

引申:位域(大疆筆試題)

C語言允許在一個結(jié)構(gòu)體中以位為單位來指定其成員所占內(nèi)存長度,這種以位為單位的成員稱為“位段”或稱“位域”( bit field) 。利用位段能夠用較少的位數(shù)存儲數(shù)據(jù)。一個位段必須存儲在同一存儲單元中,不能跨兩個單元。如果第一個單元空間不能容納下一個位段,則該空間不用,而從下一個單元起存放該位段。

1.位段聲明和結(jié)構(gòu)體類似

2.位段的成員必須是int、unsigned int、signed int

3.位段的成員名后邊有一個冒號和一個數(shù)字

  1. typedef struct_data{ 
  2.    char m:3; 
  3.    char n:5; 
  4.    short s; 
  5.      
  6.    union
  7.    int a; 
  8.    char b; 
  9.    }; 
  10.      
  11.    int h; 
  12. }_attribute_((packed)) data_t; 

答案12

m和n一起,剛好占用一個字節(jié)內(nèi)存,因為后面是short類型變量,所以在short s之前,應(yīng)該補一個字節(jié)。所以m和n其實是占了兩個字節(jié)的,然后是short兩個個字節(jié),加起來就4個字節(jié),然后聯(lián)合體占了四個字節(jié),總共8個字節(jié)了,最后int h占了四個字節(jié),就是12個字節(jié)了

attribute((packed)) 取消對齊

GNU C的一大特色就是__attribute__機制。__attribute__可以設(shè)置函數(shù)屬性(Function Attribute)、變量屬性(Variable Attribute)和類型屬性(Type Attribute)。

__attribute__書寫特征是:__attribute__前后都有兩個下劃線,并且后面會緊跟一對括弧,括弧里面是相應(yīng)的__attribute__參數(shù)。

跨平臺通信時用到。不同平臺內(nèi)存對齊方式不同。如果使用結(jié)構(gòu)體進行平臺間的通信,會有問題。例如,發(fā)送消息的平臺上,結(jié)構(gòu)體為24字節(jié),接受消息的平臺上,此結(jié)構(gòu)體為32字節(jié)(只是隨便舉個例子),那么每個變量對應(yīng)的值就不對了。

不同框架的處理器對齊方式會有不同,這個時候不指定對齊的話,會產(chǎn)生錯誤結(jié)果

12、inline函數(shù)

在C語言中,如果一些函數(shù)被頻繁調(diào)用,不斷地有函數(shù)入棧,即函數(shù)棧,會造成??臻g或棧內(nèi)存的大量消耗。為了解決這個問題,特別的引入了inline修飾符,表示為內(nèi)聯(lián)函數(shù)。

大多數(shù)的機器上,調(diào)用函數(shù)都要做很多工作:調(diào)用前要先保存寄存器,并在返回時恢復(fù),復(fù)制實參,程序還必須轉(zhuǎn)向一個新位置執(zhí)行C++中支持內(nèi)聯(lián)函數(shù),其目的是為了提高函數(shù)的執(zhí)行效率,用關(guān)鍵字 inline 放在函數(shù)定義(注意是定義而非聲明)的前面即可將函數(shù)指定為內(nèi)聯(lián)函數(shù),內(nèi)聯(lián)函數(shù)通常就是將它在程序中的每個調(diào)用點上“內(nèi)聯(lián)地”展開。

內(nèi)聯(lián)是以代碼膨脹(復(fù)制)為代價,僅僅省去了函數(shù)調(diào)用的開銷,從而提高函數(shù)的執(zhí)行效率。

13、內(nèi)存四區(qū),什么變量分別存儲在什么區(qū)域,堆上還是棧上。 


 文字常量區(qū),叫.rodata,不可以改變,改變會導(dǎo)致段錯誤

  1. int a0=1; 
  2. static int a1; 
  3. const static a2=0; 
  4. extern int a3; 
  5.  
  6. void fun(void) 
  7.  int a4; 
  8.  volatile int a5; 
  9.  return

a0 :全局初始化變量;生命周期為整個程序運行期間;作用域為所有文件;存儲位置為data段。

a1 :全局靜態(tài)未初始化變量;生命周期為整個程序運行期間;作用域為當(dāng)前文件;儲存位置為BSS段。

a2 :全局靜態(tài)變量

a3 :全局初始化變量;其他同a0。

a4 :局部變量;生命周期為fun函數(shù)運行期間;作用域為fun函數(shù)內(nèi)部;儲存位置為棧。

a5 :局部易變變量;

14、使用32位編譯情況下,給出判斷所使用機器大小端的方法。


聯(lián)合體方法判斷方法:利用union結(jié)構(gòu)體的從低地址開始存,且同一時間內(nèi)只有一個成員占有內(nèi)存的特性。大端儲存符合閱讀習(xí)慣。聯(lián)合體占用內(nèi)存是最大的那個,和結(jié)構(gòu)體不一樣。

a和c公用同一片內(nèi)存區(qū)域,所以更改c,必然會影響a的數(shù)據(jù)

  1. #include<stdio.h> 
  2.  
  3. int main(){ 
  4.   union w 
  5.   { 
  6.       int a; 
  7.       char b; 
  8.   }c; 
  9.   c.a = 1; 
  10.   if(c.b == 1) 
  11.    printf("小端存儲\n"); 
  12.   else 
  13.    printf("大端存儲\n"); 
  14.  return 0; 

指針方法

通過將int強制類型轉(zhuǎn)換成char單字節(jié),p指向a的起始字節(jié)(低字節(jié))

  1. #include <stdio.h> 
  2. int main () 
  3.     int a = 1; 
  4.     char *p = (char *)&a; 
  5.     if(*p == 1) 
  6.     { 
  7.         printf("小端存儲\n"); 
  8.     } 
  9.     else 
  10.     { 
  11.         printf("大端存儲\n"); 
  12.     } 
  13.     return 0; 

15、用變量a給出下面的定義

  1. a) 一個整型數(shù); 
  2. b)一個指向整型數(shù)的指針; 
  3. c)一個指向指針的指針,它指向的指針是指向一個整型數(shù); 
  4. d)一個有10個整型的數(shù)組; 
  5. e)一個有10個指針的數(shù)組,該指針是指向一個整型數(shù); 
  6. f)一個指向有10個整型數(shù)數(shù)組的指針; 
  7. g)一個指向函數(shù)的指針,該函數(shù)有一個整型參數(shù)并返回一個整型數(shù); 
  8. h)一個有10個指針的數(shù)組,該指針指向一個函數(shù),該函數(shù)有一個整型參數(shù)并返回一個整型數(shù) 
  9. 答案: 
  10. a)int a 
  11. b)int *a; 
  12. c)int **a; 
  13. d)int a[10]; 
  14. e)int *a [10]; 
  15. f) int a[10], *p=a; 
  16. g)int (*a)(int
  17. h) int( *a[10])(int

16、與或非,異或。運算符優(yōu)先級

sum=a&b<

其中a=3,b=5,c=4(先加再移位再&再異或)答案4

 

 

責(zé)任編輯:姜華 來源: 嵌入式Linux系統(tǒng)開發(fā)
相關(guān)推薦

2021-01-20 07:28:34

嵌入式筆試面試

2021-01-14 10:24:33

嵌入式筆試面試

2021-01-19 07:16:25

嵌入式筆試面試

2021-01-22 07:17:14

嵌入式筆試面試

2021-01-21 08:00:50

嵌入式筆試面試

2021-02-25 16:26:35

嵌入式筆試面試

2009-06-06 18:36:02

java面試題

2018-03-08 18:40:47

Java百度面試題

2011-05-19 16:30:38

軟件測試

2021-10-27 11:00:30

C++語言面試

2009-05-14 09:28:16

嵌入式面試求職

2009-06-18 15:45:55

J2ee筆試

2009-08-01 23:17:19

ASP.NET面試題目ASP.NET

2020-06-04 14:40:40

面試題Vue前端

2011-01-14 13:13:23

嵌入式Linux開發(fā)

2009-08-01 22:47:13

ASP.NET筆試題目ASP.NET

2013-11-26 13:54:00

AMD嵌入式

2013-08-01 17:42:08

AMD嵌入式SOC產(chǎn)品

2023-11-13 07:37:36

JS面試題線程

2011-03-24 13:27:37

SQL
點贊
收藏

51CTO技術(shù)棧公眾號