国产成人精品三级麻豆,色综合天天综合高清网,亚洲精品夜夜夜,国产成人综合在线女婷五月99播放,色婷婷色综合激情国产日韩

當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式招聘 > 嵌入式面試題 > 嵌入式最基本的面試題,老鳥(niǎo)總結(jié)

嵌入式最基本的面試題,老鳥(niǎo)總結(jié) 時(shí)間:2018-08-22      來(lái)源:未知

下面總結(jié)出了一下嵌入式面試中最常見(jiàn)的一些題型,而且都是每次面試都會(huì)提及到的,因?yàn)槲颐嬖嚵撕芏喙究偨Y(jié)的一些經(jīng)驗(yàn),可以收藏學(xué)習(xí)哦。

常見(jiàn)基本類型的字節(jié)大小

32位操作系統(tǒng)

char :1個(gè)字節(jié)(固定)

*(即指針變量): 4個(gè)字節(jié)(32位機(jī)的尋址空間是4個(gè)字節(jié)。同理64位編譯器)(變化*)

short int : 2個(gè)字節(jié)(固定)

int: 4個(gè)字節(jié)(固定)

unsigned int : 4個(gè)字節(jié)(固定)

float: 4個(gè)字節(jié)(固定)

double: 8個(gè)字節(jié)(固定)

long: 4個(gè)字節(jié)

unsigned long: 4個(gè)字節(jié)(變化*,其實(shí)就是尋址控件的地址長(zhǎng)度數(shù)值)

long long: 8個(gè)字節(jié)(固定)

1.指向字符串常量的指針,指向字符串的常量指針(const)

const char* p = "hello"; // 指向 "字符串常量"

p[0] = 'X'; // 錯(cuò)誤! 想要修改字符串的第一個(gè)字符. 但是常量不允許修改

p = p2; // 正確! 讓p指向另外一個(gè)指針.

char* const p = "hello"; // 指向字符串的" 常量的指針"

p[0] = 'X'; // 正確! 允許修改字符串, 因?yàn)樵撟址皇浅A?/p>

p = p2; // 錯(cuò)誤! 指針是常量, 不許修改p的指向

char const * 和 const char* 是一樣的. const 的位置在char左邊還是右邊都一樣.

常量指針的const應(yīng)當(dāng)寫(xiě)在 *星號(hào)的右邊.

指向常量字符串的常量指針的寫(xiě)法是 const char* const p = "xx"; 要2個(gè)const

2.typedef & #define的問(wèn)題

有下面兩種定義pStr數(shù)據(jù)類型的方法,兩者有什么不同?哪一種更好一點(diǎn)?

typedef char* pStr;

#define pStr char*;

分析:通常講,typedef要比#define要好,特別是在有指針的場(chǎng)合。請(qǐng)看例子:

typedef char* pStr1;

#define pStr2 char *

pStr1 s1, s2;

pStr2 s3, s4;

在上述的變量定義中,s1、s2、s3都被定義為char *,而s4則定義成了char,不是我們所預(yù)期的指針變量,根本原因就在于#define只是簡(jiǎn)單的字符串替換而typedef則是為一個(gè)類型起新名字。上例中define語(yǔ)句必須寫(xiě)成 pStr2 s3, *s4; 這這樣才能正常執(zhí)行。

3.const的問(wèn)題

(1)可以定義const常量,具有不可變性。

例如:const int Max=100; int Array[Max];

(2)便于進(jìn)行類型檢查,使編譯器對(duì)處理內(nèi)容有更多了解,消除了一些隱患。

例如: void f(const int i) { .........} 編譯器就會(huì)知道i是一個(gè)常量,不允許修改;

(3)可以避免意義模糊的數(shù)字出現(xiàn),同樣可以很方便地進(jìn)行參數(shù)的調(diào)整和修改。

如(1)中,如果想修改Max的內(nèi)容,只需要:const int Max=you want;即可!

(4)可以保護(hù)被修飾的東西,防止意外的修改,增強(qiáng)程序的健壯性。 還是上面的例子,如果在函數(shù)體內(nèi)修改了i,編譯器就會(huì)報(bào)錯(cuò);

例如: void f(const int i) { i=10;//error! }

(5)可以節(jié)省空間,避免不必要的內(nèi)存分配。 例如:

#define PI 3.14159 //常量宏

const doublePi=3.14159; //此時(shí)并未將Pi放入RAM中 ......

doublei=Pi; //此時(shí)為Pi分配內(nèi)存,以后不再分配!

double I=PI; //編譯期間進(jìn)行宏替換,分配內(nèi)存

double j=Pi; //沒(méi)有內(nèi)存分配

double J=PI; //再進(jìn)行宏替換,又一次分配內(nèi)存!

const定義常量從匯編的角度來(lái)看,只是給出了對(duì)應(yīng)的內(nèi)存地址,而不是象#define一樣給出的是立即數(shù),所以,const定義的常量在程序運(yùn)行過(guò)程中只有一份拷貝,而#define定義的常量在內(nèi)存中有若干個(gè)拷貝。

(6)提高了效率。

編譯器通常不為普通const常量分配存儲(chǔ)空間,而是將它們保存在符號(hào)表中,這使得它成為一個(gè)編譯期間的常量,沒(méi)有了存儲(chǔ)與讀內(nèi)存的操作,使得它的效率也很高。

sizeof與strlen的區(qū)別:

char str[20]="0123456789";

int a=strlen(str); // a=10;strlen 計(jì)算字符串的長(zhǎng)度,以\0'為字符串結(jié)束標(biāo)記。

int b=sizeof(str); // b=20;sizeof 計(jì)算的則是分配的數(shù)組str[20] 所占的內(nèi)存空間的大小,不受里面存儲(chǔ)的內(nèi)容影響.

上面是對(duì)靜態(tài)數(shù)組處理的結(jié)果,如果是對(duì)指針,結(jié)果就不一樣了

char* ss = "0123456789";

sizeof(ss)結(jié)果4===》ss是指向字符串常量的字符指針,sizeof 獲得的是一個(gè)指針的之所占的空間,應(yīng)該是長(zhǎng)整型的,所以是4,sizeof(*ss) 結(jié)果1===》*ss是第一個(gè)字符 其實(shí)就是獲得了字符串的第一位'0' 所占的內(nèi)存空間,是char類型的,占了1位strlen(ss)= 10如果要獲得這個(gè)字符串的長(zhǎng)度,則一定要使用 strlen

Sizeof結(jié)構(gòu)體為結(jié)構(gòu)體中定義的數(shù)據(jù)類型的總的空間(注意字節(jié)對(duì)齊)。

Sizeof對(duì)union為union中定義的數(shù)據(jù)類型的最大數(shù)據(jù)類型的大小。

5 .auto, register, static分析

auto即C語(yǔ)言中局部變量的默認(rèn)屬性,編譯器默認(rèn)所有的局部變量都是auto的,定義的變量都是在棧中分配內(nèi)存。

static關(guān)鍵字指明變量的“靜態(tài)”屬性,同時(shí)具有“作用域限定符”的意義,修飾的局部變量存儲(chǔ)在程序靜態(tài)區(qū),static的另一個(gè)意義是文件作用域標(biāo)示符。

static修飾的全局變量作用域只是聲明的文件中,static修飾的函數(shù)作用域只是聲明的文件中

register關(guān)鍵字指明將變量存儲(chǔ)于寄存器中,register只是請(qǐng)求寄存器變量,但不一定請(qǐng)求成功。register變量的必須是CPU寄存器可以接受的值,不能用&運(yùn)算符獲取register變量的地址,這樣使用的好處是處理快。

6. const, volatile同時(shí)修飾變量

(1) “編譯器一般不為const變量分配內(nèi)存,而是將它保存在符號(hào)表中,這使得它成為一個(gè)編譯期間的值,沒(méi)有了存儲(chǔ)與讀內(nèi)存的操作。”

(2) volatile的作用是“告訴編譯器,i是隨時(shí)可能發(fā)生變化的,每次使用它的時(shí)候必須從內(nèi)存中取出i的值”。

一,const, volatile含義

(1)const含義是“請(qǐng)做為常量使用”,而并非“放心吧,那肯定是個(gè)常量”。

(2)volatile的含義是“請(qǐng)不要做自以為是的優(yōu)化,這個(gè)值可能變掉的”,而并非“你可以修改這個(gè)值”。

二,const, volatile的作用以及起作用的階段

(1)const只在編譯期有用,在運(yùn)行期無(wú)用

const在編譯期保證在C的“源代碼”里面,沒(méi)有對(duì)其修飾的變量進(jìn)行修改的地方(如有則報(bào)錯(cuò),編譯不通過(guò)),而運(yùn)行期該變量的值是否被改變則不受const的限制。

(2)volatile在編譯期和運(yùn)行期都有用

在編譯期告訴編譯器:請(qǐng)不要做自以為是的優(yōu)化,這個(gè)變量的值可能會(huì)變掉;

在運(yùn)行期:每次用到該變量的值,都從內(nèi)存中取該變量的值。

補(bǔ)充:編譯期 -- C編譯器將源代碼轉(zhuǎn)化為匯編,再轉(zhuǎn)化為機(jī)器碼的過(guò)程;運(yùn)行期 -- 機(jī)器碼在CPU中執(zhí)行的過(guò)程。

三,const, volatile同時(shí)修飾一個(gè)變量

(1)合法性

“volatile”的含義并非是“non-const”,volatile和cons不構(gòu)成反義詞,所以可以放一起修飾一個(gè)變量。

(2)同時(shí)修飾一個(gè)變量的含義

表示一個(gè)變量在程序編譯期不能被修改且不能被優(yōu)化;在程序運(yùn)行期,變量值可修改,但每次用到該變量的值都要從內(nèi)存中讀取,以防止意外錯(cuò)誤。

7 、棧、堆、靜態(tài)存儲(chǔ)區(qū)

棧:主要函數(shù)調(diào)用的使用

棧是從高地址向低地址方向使用,堆的方向相反。

在一次函數(shù)調(diào)用中,棧中將被依次壓入:參數(shù),返回地址,EBP。如果函數(shù)有局部變量,接下來(lái),就在棧中開(kāi)辟相應(yīng)的空間以構(gòu)造變量。

在C語(yǔ)言程序中,參數(shù)的壓棧順序是反向的。比如func(a,b,c)。在參數(shù)入棧的時(shí)候,是:先壓c,再壓b,最后a。在取參數(shù)的時(shí)候,由于棧的先入后出,先取棧頂?shù)腶,再取b,最后取c。

堆:主要內(nèi)存動(dòng)態(tài)分配

空閑鏈表法,位圖法,對(duì)象池法等等 。

Int* p=(int*)malloc(sizeof(int));

靜態(tài)存儲(chǔ)區(qū):保存全局變量和靜態(tài)變量

程序靜態(tài)存儲(chǔ)區(qū)隨著程序的運(yùn)行而分配空間,直到程序運(yùn)行結(jié)束,在程序的編譯期靜態(tài)存儲(chǔ)區(qū)的大小就已經(jīng)確定,程序的靜態(tài)存儲(chǔ)區(qū)主要用于保存程序中的全局變量和靜態(tài)變量與棧和堆不同,靜態(tài)存儲(chǔ)區(qū)的信息最終會(huì)保存到可執(zhí)行程序中 。

知識(shí)點(diǎn):堆棧段在程序運(yùn)行后才正式存在,是程序運(yùn)行的基礎(chǔ)

1.函數(shù)放在代碼段:.Test section。 .text段存放的是程序中的可執(zhí)行代碼

2.帶初始值的全局變量和靜態(tài)變量在數(shù)據(jù)段:.data section。 .data段保存的是那些已經(jīng)初始化了的全局變量和靜態(tài)變量

3.不帶初始值得全局變量和靜態(tài)變量在.bss。 .bss段存放的是未初始化的全局變量和靜態(tài)變量

.rodata(read only)段存放程序中的常量值,如字符串常量

同是全局變量和靜態(tài)變量,為什么初始化和未初始化的變量保存在不同的段中?

答:為了啟動(dòng)代碼的簡(jiǎn)單化,編譯鏈接器會(huì)把已初始化的變量放在同一個(gè)段:.data,這個(gè)段的映像(包含了各個(gè)變量的初值)保存在“只讀數(shù)據(jù)段”,這樣啟動(dòng)代碼就可以簡(jiǎn)單地復(fù)制這個(gè)映像到 .data 段,所有的已初始化變量就都初始化了。而未初始化變量也放在同一個(gè)段:.bss,啟動(dòng)代碼簡(jiǎn)單地調(diào)用 memset 就可以把所有未初始化變量都清0。

void *memset(void *s, int ch, size_t n);

函數(shù)解釋:將s中當(dāng)前位置后面的n個(gè)字節(jié) (typedef unsigned int size_t )用 ch 替換并返回 s 。

memset:作用是在一段內(nèi)存塊中填充某個(gè)給定的值,它是對(duì)較大的結(jié)構(gòu)體或數(shù)組進(jìn)行清零操作的一種最快方法

#define Malloc(type,n) (type*)malloc(n*sizeof(type))

8 、野指針

產(chǎn)生原因:

1、局部指針變量沒(méi)有初始化

2、使用已經(jīng)釋放的指針

3、指針?biāo)赶虻淖兞吭谥羔樦氨讳N毀

A.用malloc申請(qǐng)了內(nèi)存之后,應(yīng)該立即檢查指針值是否為NULL,防止使用為NULL的指針:

B.牢記數(shù)組的長(zhǎng)度,防止數(shù)組越界操作,考慮使用柔性數(shù)組

C.動(dòng)態(tài)申請(qǐng)操作必須和釋放操作匹配,防止內(nèi)存泄露和多次釋放

D.free指針之后必須立即賦值為NULL

9 、void類型指針

指針有兩個(gè)屬性:指向變量/對(duì)象的地址和長(zhǎng)度,但是指針只存儲(chǔ)地址,長(zhǎng)度則取決于指針的類型;編譯器根據(jù)指針的類型從指針指向的地址向后尋址,指針類型不同則尋址范圍也不同,比如:

int*從指定地址向后尋找4字節(jié)作為變量的存儲(chǔ)單元

double*從指定地址向后尋找8字節(jié)作為變量的存儲(chǔ)單元

void即“無(wú)類型”,void *則為“無(wú)類型指針”,可以指向任何數(shù)據(jù)類型。

void指針可以指向任意類型的數(shù)據(jù),即可用任意數(shù)據(jù)類型的指針對(duì)void指針賦值。例如

int *pint;

void *pvoid; //它沒(méi)有類型,或者說(shuō)這個(gè)類型不能判斷出指向?qū)ο蟮拈L(zhǎng)度

pvoid = pint; //只獲得變量/對(duì)象地址而不獲得大小,但是不能 pint =pvoid;

9.2 如果要將pvoid賦給其他類型指針,則需要強(qiáng)制類型轉(zhuǎn)換如:

pint = (int *)pvoid; //轉(zhuǎn)換類型也就是獲得指向變量/對(duì)象大小

9.3 void指針不能復(fù)引用(即取內(nèi)容的意思)

*pvoid //錯(cuò)誤

要想復(fù)引用一個(gè)指針,或者使用“->”運(yùn)算符復(fù)引用一部分,都要有對(duì)于指針指向的內(nèi)存的解釋規(guī)則。

例如,int *p;

那么,當(dāng)你后面復(fù)印用p的時(shí)候,編譯器就會(huì)把從p指向的地址開(kāi)始的四個(gè)字節(jié)看作一個(gè)整數(shù)的補(bǔ)碼。

因?yàn)関oid指針只知道指向變量/對(duì)象的起始地址,而不知道指向變量/對(duì)象的大小(占幾個(gè)字節(jié))所以無(wú)法正確引用。

在實(shí)際的程序設(shè)計(jì)中,為迎合ANSI標(biāo)準(zhǔn),并提高程序的可移植性,我們可以這樣編寫(xiě)實(shí)現(xiàn)同樣功能的代碼:

void*pvoid;

(char*)pvoid++; //ANSI:正確;GNU:正確

(char*)pvoid+=1; //ANSI:錯(cuò)誤;GNU:正確

上一篇:Java面試題(附答案)

下一篇:嵌入式C語(yǔ)言面試題大集合,都是自己總結(jié)的

熱點(diǎn)文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗(yàn)分享
熱點(diǎn)新聞推薦
前臺(tái)專線:010-82525158 企業(yè)培訓(xùn)洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠(yuǎn)見(jiàn)科技集團(tuán)有限公司 版權(quán)所有 ,京ICP備16055225號(hào)-5,京公海網(wǎng)安備11010802025203號(hào)

回到頂部