面試題—宏、函數、宏函數、inline函數的區別與聯繫


--宏和函數:


       。宏其實主要是進行字符串的替換(只是進行字符串的替換,不涉及類型參數),而函數是通過參數的傳遞,參數是有數據類型的。

       。編譯器在預處理階段就會進行宏的替換,不會進行參數的檢查,而函數調用是將值傳遞給形參(值傳遞、引用傳遞、指針傳遞),在編譯階段之後,執行函數是會對參數進行檢查的。


解釋:例如:#define  MAX    1000     這個宏在程序的預處理階段會將所有的字符串MAX直接更改爲數據1000,不涉及參數,也不會進行參數的檢查。而函數 int MAX(int  num1, int num2);這個函數是通過傳值的方式,對參數num1和num2進行int類型的檢查。如果類型不匹配,編譯器就會報錯。 


       。宏的參數不會佔用內存空間,因爲在預處理階段時,宏替換已經完成。而函數調用時的參數傳遞是作爲函數的局部變量的,編譯器會將函數的參數進行壓棧,這樣就會佔用存儲空間。

       。函數調用會花費一定的時空開銷,系統在調用函數時,需要保留現場,然後轉入被調用的函數中執行,執行完後,在返回到主調函數中繼續執行。宏中不需要。


解釋:當程序在執行主調函數的時候,如果調用其它函數的時候,就需要先將主調函數先前的執行位置數據記錄下來,將數據保存在棧中,同時在執行被調用的函數,需要將被調用函數中的參數(相當於局部變量)壓入棧中,執行完被調函數先前壓入棧中的局部變量就會出棧,被釋放。所以如果返回被調函數的局部變量就會出現錯誤。這個過程就會花費一部分CPU的時間。



   —內聯函數


       。內聯函數其實就是將很簡單的函數“嵌”到程序中,避免函數調用會花費很長的時間,減少程序運行的時間,提高效率。作爲內聯函數不能過於複雜,如果過於複雜的話,顯示聲明函數爲內聯函數,編譯器不一定會將這個函數作爲內聯函數來處理。其實,對於一個簡單的函數(沒有複雜的循環等結構)編譯器也可能會自動將函數作爲內聯函數來處理。

        “內聯函數不會出現上面花費CPU時間的過程”

     

       。在C++中,如果在類中定義的成員函數,編譯器會將其作爲內聯函數來進行處理,如果在類外定義時,還想將函數作爲內聯函數,就必須顯示的聲明。


       。將函數聲明爲內聯函數會提高程序運行的效率。因爲內聯函數是將函數“嵌”入到程序中,它不會進行函數調用,不會花費函數調用在保留現場、和儲存數據的時間。



   —宏函數、函數
       。宏函數會佔用大量的空間,因爲它採用的方式是進行宏替換,對於一個頻繁需要宏替換,需要的空間會明顯的增大。函數是消耗時間,在函數調用時,會將所需要的數據進行壓棧,需要數據時會進行出棧,cpu就會花費時間,同時進行現場的保護也會花費時間。


例如:

//宏函數

#define ABS(a) ((a) > 0 ? (a) : -(a))
int sum_array(int* x, int n)
{
 int sum = 0;
 for (int i = 0; i < n;)
 {
  sum += ABS(x[i++]);   
  /*尋找錯誤:
  宏替換會將上一句替換爲sum += ((x[i++] > 0 ? (x[i++]) : -(x[i++])));
  這個將會使得i在循環中的一次會增加2,即i = i + 2;使得sum只能求數組中部分元素之和,
  更改後i每次只會+1,下面是更改過後的代碼:
  for(int i = 0; i < n; i++)
  {
      sum += ABS(x[i]);
  }
  */
 }
 return sum;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章