1024国产,91精品国产综合久久福利,中文字幕成人免费视频,日本人的色道免费网站,曰本一级毛片免费,www.日日爱,国产黑丝视频

經(jīng)典c語言筆試題和面試題答案(二)

更新:2023-09-20 10:13:56 高考升學(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文件包含的頭文件中?為什么?

  【標準答案】可以

最新圖文