當前位置:高考升學(xué)網(wǎng) > 招聘筆試題 > 正文
67.
#include
#include
int modifyvalue()
{
int x;
return(x+=10);
}
int changevalue(int x)
{
x+=1;
return(x);
}
int main(int argc,charargv[])
{
int x=10;
x++;
x=changevalue(x);
printf("changevalue:%d\n",x);//12
x++;
modifyvalue();
printf("Firstoutput:%d\n",x);//13
x++;
x=changevalue(x);//15
printf("Secondoutput:%d\n",x);
modifyvalue();
printf("Thirdoutput:%d\n",x);//15
return 1;
}
int modifyvalue()
{
int x;
return(x+=10);
}
int changevalue(int x)
{
x+=1;
return(x);
}
int main(int argc,charargv[])
{
int x=10;
x++;
changevalue(x);//變量沒有接受返回值
printf("changevalue:%d\n",x);//11
x++;
modifyvalue(); //無形參
printf("Firstoutput:%d\n",x);//12
x++;
changevalue(x);//15
printf("Secondoutput:%d\n",x);//13
modifyvalue();
printf("Thirdoutput:%d\n",x);//13
return 1;
}
考查臨時變量(返回值為棧中變量)的生存期:僅僅在于 緊跟著的一條語句;
73、下面的代碼輸出是什么,為什么?
void foo(void)
{
unsigned inta = 6;
int b = -20;
(a+b> 6)? puts("> 6") : puts("<= 6");
}
【參考答案】這個問題測試你是否懂得C語言中的整數(shù)自動轉(zhuǎn)換原則,
我發(fā)現(xiàn)有些開發(fā)者懂得極少這些東西。不管如何,這無符號整型問題的答案是輸出是“>6”。
原因是當表達式中存在有符號類型和無符號類型時所有的數(shù)都自動轉(zhuǎn)換為無符號類型。
因此-20變成了一個非常大的正整數(shù),所以該表達式計算出的結(jié)果大于6。
這一點對于應(yīng)當頻繁用到無符號數(shù)據(jù)類型的嵌入式系統(tǒng)來說是豐常重要的
74、評價下面的代碼片斷:
unsigned intzero = 0;
unsigned intcompzero= 0xFFFF;
/1‘s complement of zero /
【參考答案】對于一個int型不是16位的處理器為說,上面的代碼是不正
確的。應(yīng)編寫如下:
unsigned intcompzero= ~0;
這一問題真正能揭露出應(yīng)試者是否懂得處理器字長的重要性。在我的經(jīng)
驗里,好的嵌入式程序員非常準確地明白硬件的細節(jié)和它的局限,然而
PC機程序往往把硬件作為一個無法避免的煩惱。
75.
char ptr;
if ((ptr= (char )malloc(0)) ==NULL)
puts("Gota nullpointer");
else
puts("Gota validpointer");
如果所請求的空間大小為0,其行為由庫的實現(xiàn)者定義:可以返回空指針,也可以讓效果跟申某個非0大小的空間一樣,所不同的是返回的指針不可以被用來訪問一個對象。
為什么 new T[0] 和 malloc(0) 不返回空指針
首先需要說明的是,按照C++標準,成功的 new T[0] 是不能返回空指針的。而 malloc(0),C 語言標準則指出,成功的時候可以返回空指針,也可以返回非空指針,多數(shù)庫一般也選擇了返回非空指針這種行為。
76.
int main(int argc,char argv[])
{
char a='a',b='b';
int p,c,d;
p=a;
p=(p<<8)|b;
d=p&0xff;
c=(p&0xff00)>>8;
printf("a=%d\nb=%d\nc=%d\nd=%d\n",a,b,c,d);
return 1;
}
[運行結(jié)果]:97,98,97,98
77.
int main(int argc,char argv[])
{
unsigned a,b;
printf("please input a number:");
scanf("%d",&a);
b=a>>5;
b=b&15;
printf("a=%d\tb=%d\n",a,b);
return 1;
}
【運行結(jié)果】:輸入 64,輸出2
概念區(qū)別
指針數(shù)組:存放指針的數(shù)組;
Int ptr[4]; (等同于二級指針 int ptr)
一級指針是指向定義類型的內(nèi)存地址,二級指針就是指向定義類型的內(nèi)存地址所指向的新的內(nèi)存地址
應(yīng)用:指向若干字符串,整形數(shù)據(jù)等,使得元素處理更加方便;其中元素存放各對應(yīng)地址;
此時,一級指針只能尋址到字符串所在的位置,并不能將其輸出,因為沒有其首地址,而p則完成二級尋址,找到了位置,也找到了它的首地址,所以能輸出
數(shù)組指針:指向一個數(shù)組的指針;
Int (ptr)[4]
應(yīng)用:可以應(yīng)用在二維數(shù)組中;
指針函數(shù):返回指針值得函數(shù)
Int search(int num);
函數(shù)指針:指向函數(shù)的指針
Int (ptr)(int num);/申明一個函數(shù)指針/
Ptr=fun();/將fun函數(shù)地址付給指針ptr/
Int a=fun(6).等價于,int a=(ptr)(6);
函數(shù)指針數(shù)組:int(s[10])(int) 函數(shù)指針數(shù)組
27、關(guān)鍵字volatile有什么含意?并給出三個不同的例子。
它是用來修飾被不同線程訪問和修改的變量。
如果沒有volatile,基本上會導(dǎo)致:要么無法編寫多線程程序,要么編譯器失去大量優(yōu)化的機會。volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設(shè)這個變量的值了。精確地說就是,優(yōu)化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:
1). 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)
存儲器映射的硬件寄存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義;
2). 一個中斷服務(wù)子程序中會訪問到的非自動變量(Non-automatic variables)
中斷服務(wù)程序中修改的供其它程序檢測的變量需要加volatile;
3). 多線程應(yīng)用中被幾個任務(wù)共享的變量
多任務(wù)環(huán)境下各任務(wù)間共享的標志應(yīng)該加volatile
3個關(guān)聯(lián)的問題:
1). 一個參數(shù)既可以是const還可以是volatile嗎?解釋為什么。
2). 一個指針可以是volatile 嗎?解釋為什么。
3). 下面的函數(shù)有什么錯誤:
int square(volatile int ptr)
{
return ptr ptr;
}
下面是答案:
1). 是的。一個例子是只讀的狀態(tài)寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應(yīng)該試圖去修改它。
2). 是的。盡管這并不很常見。一個例子是當一個中服務(wù)子程序修該一個指向一個buffer的指針時。
3). 這段代碼的有個惡作劇。這段代碼的目的是用來返指針ptr指向值的平方,但是,由于ptr指向一個volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼:
int square(volatile int ptr)
{
int a,b;
a = ptr;
b = ptr;
return a b;
}
由于ptr的值可能被意想不到地該變,因此a和b可能是不同的。結(jié)果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
long square(volatile int ptr)
{
int a;
a = ptr;
return a a;
}
37、Heap與stack的差別。
【標準答案】Heap是堆,stack是棧。
Stack的空間由操作系統(tǒng)自動分配/釋放,Heap上的空間手動分配/放。
Stack空間有限,Heap是很大的自由存儲區(qū)
C中的malloc函數(shù)分配的內(nèi)存空間即在堆上,C++中對應(yīng)的是new操符。
程序在編譯期對變量和函數(shù)分配內(nèi)存都在棧上進行,且程序運行過程中函數(shù)調(diào)用時參數(shù)的傳遞也在棧上進行
40、帶參宏與帶參函數(shù)的區(qū)別(至少說出5點)?
帶參宏 帶參函數(shù)
處理時間:編譯時 運行時
參數(shù)類型:無 定義類型
程序長度:變長 不變
占用存儲空間:否 是
運行時間:不占用 調(diào)用和返回占用時間
38.用宏定義寫出swap(x,y),即交換兩數(shù)
#define swap(x, y) (x)=(x)+(y);(y)=(x)–(y);(x)=(x)–(y);
39. 寫一個“標準”宏,這個宏輸入兩個參數(shù)并返回較小的一個。
#define Min(X, Y) ((X)>(Y)?(Y):(X)) //結(jié)尾沒有;
43、已知一個數(shù)組table,用一個宏定義,求出數(shù)據(jù)的元素個數(shù)。
【標準答案】#define NTBL(table) (sizeof(table)/sizeof(table[0]))
1. 用預(yù)處理指令#define 聲明一個常數(shù),用以表明1年中有多少秒(忽略閏年問題)
#define SECONDS_PER_YEAR (60 60 24 365)UL
總結(jié):有關(guān)宏定義#define 的基本語法
1#define的概念
#define命令是C語言中的一個宏定義命令,它用來將一個標識符定義為一個字符串,該標識符被稱為宏名,被定義的字符串稱為替換文本。
該命令有兩種格式:一種是簡單的宏定義,另一種是帶參數(shù)的宏定義。
(1) 簡單的宏定義:
#define <宏名> <字符串>
例:#define PI 3.1415926
(2) 帶參數(shù)的宏定義
#define <宏名>(<參數(shù)表>) <宏體>
例:#defineA(x) x
一個標識符被宏定義后,該標識符便是一個宏名。
這時,在程序中出現(xiàn)的是宏名,在該程序被編譯前,先將宏名用被定義的字符串替換,這稱為宏替換,替換后才進行編譯,宏替換是簡單的替換。
2.宏定義的缺點
在簡單宏定義的使用中,當替換文本所表示的字符串為一個表達式時,容易引起誤解和誤用。如下例:
例1 #define N 2+2
void main()
{
int a=NN;
printf(“%d”,a);
}
(1) 出現(xiàn)問題:在此程序中存在著宏定義命令,宏N代表的字符串是2+2,該題的結(jié)果為8,
(2) 問題解析:宏展開是在預(yù)處理階段完成的,這個階段把替換文本只是看作一個字符串,并不會有任何的計算發(fā)生,在展開時是在宏N出現(xiàn)的地方只是簡單地使用串2+2來代替N,并不會增添任何的符號,所以對該程序展開后的結(jié)果是a=2+22+2,計算后=8,這就是宏替換的實質(zhì),如何寫程序才 能完成結(jié)果為16的運算呢?
(3)解決辦法:將宏定義寫成如下形式
#define N (2+2)
這樣就可替換成(2+2)(2+2)=16
在帶參數(shù)的宏定義的使用中,極易引起誤解。例如我們需要做個宏替換能求任何數(shù)的平方,這就需要使用參數(shù),以便在程序中用實際參數(shù)來替換宏定義中的參數(shù)。一般學(xué)生容易寫成如下形式:
#define area(x) xx
這在使用中是很容易出現(xiàn)問題的,看如下的程序
void main()
{
int y=area(2+2);
printf(“%d”,y);
}
按 理說給的參數(shù)是2+2,所得的結(jié)果應(yīng)該為44=16,但是錯了,因為該程序的實際結(jié)果為8,仍然是沒能遵循純粹的簡單替換的規(guī)則,又是先計算再替換了,在這道程序里,2+2即為area宏中的參數(shù),應(yīng)該由它來替換宏定義中的x,即替換成2+22+2=8了。那如果遵循(1)中的解決辦法,把2+2 括起來,即把宏體中的x括起來,是否可以呢?#define area(x) (x)(x),對于area(2+2),替換為(2+2)(2+2)=16,可以解決,但是對于area(2+2)/area(2+2)又會怎么樣 呢,這道題替換后會變?yōu)?(2+2)(2+2)/(2+2)(2+2)即44/44按照乘除運算規(guī)則,結(jié)果為16/44=44=16,那應(yīng)該怎么呢?解決方法是在整個宏體上再加一個括號,即
#define area(x) ((x)(x)),不要覺得這沒必要,沒有它,是不行的。
要想能夠真正使用好宏 定義,
一定要記住先將程序中對宏的使用全部替換成它所代表的字符串,不要自作主張地添加任何其他符號,完全展開后再進行相應(yīng)的計算,就不會寫錯運行結(jié)果。
如果是自己編程使用宏替換,則在使用簡單宏定義時,當字符串中不只一個符號時,加上括號表現(xiàn)出優(yōu)先級,如果是 帶參數(shù)的宏定義,則要給宏體中的每個參數(shù)加上括號,并在整個宏體上再加一個括號。
宏定義的優(yōu)點:
(1) 方便程序的修改
使用簡單宏定義可用宏代替一個在程序中經(jīng)常使用的常量,這樣在將該常量改變時,不用對整個程序進行修改,只修改宏定義的字符串即可,而且當常量比較長時, 我們可以用較短的有意義的標識符來寫程序,這樣更方便一些。
(2) 提高程序的運行效率
使用帶參數(shù)的宏定義可完成函數(shù)調(diào)用的功能,又能 減少系統(tǒng)開 銷,提高運行效率。正如C語言中所講,函數(shù)的使用可以使程序更加模塊化,便于組織,而且可重復(fù)利用,但在發(fā)生函數(shù)調(diào)用時,需要保留調(diào)用函數(shù)的現(xiàn)場,以便子函數(shù)執(zhí)行結(jié)束后能返回繼續(xù)執(zhí)行,同樣在子函數(shù)執(zhí)行完后要恢復(fù)調(diào)用函數(shù)的現(xiàn)場,這都需要一定的時間,如果子函數(shù)執(zhí)行的操作比較多,這種轉(zhuǎn)換時間開銷可以忽略,但如果子函數(shù)完成的功能比較少,甚至于只完成一點操作,如一個乘法語句的操作,則這部分轉(zhuǎn)換開銷就相對較大了,但使用帶參數(shù)的宏定義就不會出現(xiàn)這個問題,因為它是在預(yù)處理階段即進行了宏展開,在執(zhí)行時不需要轉(zhuǎn)換,即在當?shù)貓?zhí)行。宏定義可完成簡單的操作,但復(fù)雜的操作還是要由函數(shù)調(diào)用來完成,而且宏定義所占用的目標代碼空間相對較大。所以在使用時要依據(jù)具體情況來決定是否使用宏定義。
49、什么是預(yù)編譯,何時需要預(yù)編譯:
【標準答案】1、總是使用不經(jīng)常改動的大型代碼體
2、程序由多個模塊組成,所有模塊都使用一組標準的包含文件和相同的編譯選項。在這種情況下,可以將所有包含文件預(yù)編譯為一個預(yù)編譯頭。
53、Typedef在C語言中頻繁用以聲明一個已經(jīng)存在的數(shù)據(jù)類型的同義字。也可以用預(yù)處理器做類似的事。
如,思考一下下面的例子:
#define dPSstructs
typedefstructs tPS;
以上兩種情況的意圖都是要定義dPS和tPS作為一個指向結(jié)構(gòu)s指針。哪種方法更好呢?
答案是:typedef更好。思考下面的例子:
dPSp1,p2;
tPSp3,p4;
第一個擴展為
structs p1, p2;
上面的代碼定義p1為一個指向結(jié)構(gòu)的指,p2為一個實際的結(jié)構(gòu),這也許
不是你想要的。第二個例子正確地定義了p3 和p4 兩個指針。
54.在C++ 程序中調(diào)用被C 編譯器編譯后的函數(shù),為什么要加extern “C”?
重點就是C++里面支持函數(shù)的重載,因此編譯出來的.obj或者庫文件里面,函數(shù)名會被加上和參數(shù)有關(guān)的簽名,用來區(qū)分同樣函數(shù)名參數(shù)不同的函數(shù)。然而C語言不支持重載,所以函數(shù)名里面沒有這樣的簽名。
這樣,當C語言的程序調(diào)用C++寫成的庫的時候,就會找不到函數(shù)。比如,一個函數(shù)叫 void foo(int bar)之類的,可能會在c++編譯成叫 foo_i之類的名字,而在c語言里面就會編譯成foo,這樣c語言的程序去找foo就會找不到,這樣連接的時候會出錯。
為了解決這個問題,引入了extrn "c"{},在這個的作用域之內(nèi),c++的函數(shù)名不會加上參數(shù)簽名,和c語言的標準保持統(tǒng)一,就兼容c語言的程序了。
2、中斷是嵌入式系統(tǒng)中重要的組成部分,這導(dǎo)致了很多編譯開發(fā)商提供一種擴展—讓標準C支持中斷。具代表事實是,產(chǎn)生了一個新的關(guān)鍵字__interrupt。下面的代碼就使用了__interrupt關(guān)鍵字去定義了一個中斷服務(wù)子程序(ISR),請評論一下這段代碼的。
__interrupt double compute_area(double radius)
{
double area = PI radius radius;
printf(" Area = %f", area);
return area;
}
【參考答案】這個函數(shù)有太多的錯誤了,以至讓人不知從何說起了:
1). ISR 不能返回一個值。如果你不懂這個,那么你不會被雇用的。
2). ISR 不能傳遞參數(shù)。如果你沒有看到這一點,你被雇用的機會等同第
一項。
3). 在許多的處理器/編譯器中,浮點一般都是不可重入的。有些處理器/編
譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做
浮點運算。此外,ISR應(yīng)該是短而有效率的,在ISR中做浮點運算是不明
智的。
4). 與第三點一脈相承,printf()經(jīng)常有重入和性能上的問題。如果你丟掉
了第三和第四點,我不會太為難你的。
35、全局變量可不可以定義在可被多個.C文件包含的頭文件中?為什么?
【標準答案】可以
2020年河北新聞網(wǎng)兩學(xué)一做
時間:2023-09-18 07:0:242020年河北新聞網(wǎng)兩學(xué)一做
時間:2023-09-15 11:0:59兩學(xué)一做學(xué)習(xí)教育知
時間:2023-09-21 06:0:302020年開展兩學(xué)一做學(xué)習(xí)教
時間:2023-09-19 21:0:30