移動計算機面試問題經驗

才智咖 人氣:1.74W

C語言考查的重點一般是:指標、結構體、條件編譯、全域性變數/區域性變數。以下是

移動計算機面試問題經驗

我遇見過的面試問題:

1)請說一下extern C的作用(漢略)

Extern “C”是由C++提供的一個連線交換指定符號,用於告訴C++這段程式碼是C函式。這是因為C++編譯後庫中函式名會變得很長,與C生成的不一致,造成C++不能直接呼叫C函式,加上extren “c”後,C++就能直接呼叫C函數了。

Extern “C”主要使用正規DLL函式的引用和匯出和 在C++包含C函式或C標頭檔案時使用。使用時在前面加上extern “c” 關鍵字即可

extern是C/C++語言中表明函式和全域性變數作用範圍(可見性)的關鍵字,該關鍵字告訴編譯器,其宣告的函式和變數可以在本模組或其它模組中使用。記住,下列語句:

extern int a;

僅僅是一個變數的宣告,其並不是在定義變數a,並未為a分配記憶體空間。變數a在所有模組中作為一種全域性變數只能被定義一次,否則會出現連線錯誤。

通常,在模組的標頭檔案中對本模組提供給其它模組引用的函式和全域性變數以關鍵字extern宣告。例如,如果模組B欲引用該模組A中定義的全域性變數和函式時只需包含模組A的標頭檔案即可。這樣,模組B中呼叫模組A中的函式時,在編譯階段,模組B雖然找不到該函式,但是並不會報錯;它會在連線階段中從模組A編譯生成的目的碼中找到此函式。(

一、修飾名(Decorated Name)

C/C++程式中的函式在內部是通過修飾名來標識的。修飾名是在函式定義或原型編譯階段由編譯器建立字串。當你在LINK等工具中要指定一個函式名時,會用到修飾名。

1、使用修飾名:

大多數情況下,你不必知道函式的修飾名是什麼。聯結器等工具通常都能處理函式未修飾的名字。然而,在有些情況下,你可能需要指定函式的修飾名。對於C++過載函式和特定的成員函式(如:建構函式和解構函式),你必須指定這些函式的修飾名,以便聯結器等工具能夠匹配名字。同時,你也必須在那些引用c或c++函式名的彙編原始檔中使用修飾名。

2、檢視修飾名:

如果你編譯了一個原始檔,該原始檔中包含了函式定義或原型,你可以獲得函式的修飾名形式。

(1)用編譯器列表(compiler listing)來檢視:

(i)通過將列表檔案型別編譯器選項(/FA[c|s]) 設定為下面中的一種,來產生列表檔案:Assembly with Machine Code (/FAc); Assembly with Source Code (/FAs); Assembly, Machine Code, and Source (/FAcs).

(ii)在產生的列表檔案中,找到包含未經修飾的函式定義的行。

(iii)查詢前面一行。PROC NEAR 命令標籤前就是函式名經過修飾後的形式。

(2)使用DUMPBIN工具來檢視:

在或上執行DUMPBIN,使用/SYMBOLS選項。在輸出中查詢未經修飾的函式定義。後面跟著的就是經過修飾的函式名,用圓括號括起來的。

二、替代連線說明:

如果在c++中編寫一個程式需要用到c的庫,那該如何?如果這樣宣告一個c函式:

void f(int a,char b);

c++編譯器就會將這個名字變成相應的修飾名,比如:?f@@YAXHD@Z。

然而,c編譯器編譯的庫的內部函式名(聯結器使用)是完全不同的。這樣,當c++聯結器連線c的函式庫時,將會產生內部使用函式不匹配。

故,c++中提供了一個替代連線說明(alternate linkage specification),它是通過過載extern關鍵字來實現的。

extern後跟一個字串來指定想宣告的函式的連線型別,後面是函式宣告,比如:

extern "C" void f(int a,char b);

這樣,就是告訴編譯器是c連線,這樣就不會轉換函式名了。此例中,編譯後的內部函式名是_f。

2)請說一下#ifdef...的作用(漢略)

#ifdef的作用大體上是工程功能的切換,通常是根據某些巨集是否定義來決定是否啟用某些功能。比如網路監控系統,通過巨集的切換,可以實現平臺的移植,視屏路數的定義,雲臺、矩陣和透明串列埠的切換,等等。由於#ifdef的存在,靜態配置一下引數即可讓firmware實現不同的功能。

1.利用#ifdef/#endif將某程式功能模組包括進去,以向某使用者提供該功能。

在程式首部定義#ifdef HNLD:

#ifdef HNLD

include"n166_hn.c"

#endif

如果不許向別的使用者提供該功能,則在編譯之前將首部的HNLD加一下劃線即可。

2.在每一個子程式前加上標記,以便追蹤程式的執行。

#ifdef DEBUG

printf(" Now is in hunan !");

#endif

3.避開硬體的限制。有時一些具體應用環境的硬體不一樣,但限於條件,本地缺乏這種裝置,於是繞過硬體,直接寫出預期結果。具體做法是:

#ifndef TEST

i=dial();

//程式除錯執行時繞過此語句

#else

i=0;

#endif

除錯通過後,再遮蔽TEST的定義並重新編譯,即可發給使用者使用了。

3)C語言裡,哪些變數是存放在堆裡,哪些是存放在棧裡?(普天)

heap area存放程式的動態資料

stack area存放程式的區域性資料

1、棧區(stack)— 由編譯器自動分配釋放,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。地址是由高向低減少的

2、堆區(heap)— 一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由OS回收。注意它與資料結構中的堆是兩回事,分配方式倒是類似於連結串列,呵呵。地址是由低向高增長的

4)C語言裡的static關鍵詞是什麼含義?(普天)

與extern對應的關鍵字是static,被它修飾的全域性變數和函式只能在本模組中使用。因此,一個函式或變數只可能被本模組使用時,其不可能被extern “C”修飾。

5)程序和執行緒有什麼區別?(普天)

執行緒的引入:例如,有一個Web伺服器要程序的方式併發地處理來自不同使用者的網頁訪問請求的話,可以建立父程序和多個子程序的方式來進行處理,但是建立一個程序要花費較大的系統開銷和佔用較多的資源。除外,這些不同的使用者子程序在執行的時候涉及到程序上下文切換,上下文切換是一個複雜的過程。所以,為了減少程序切換和建立的開銷,提高執行效率和節省資源,人們在作業系統中引入了"執行緒(thread)"的概念。

程序的作用和定義:程序是為了提高CPU的執行效率,減少因為程式等待帶來的CPU空轉以及其他計算機軟硬體資源的浪費而提出來的`。程序是為了完成使用者任務所需要的程式的一次執行過程和為其分配資源的一個基本單位,是一個具有獨立功能的程式段對某個資料集的一次執行活動。

執行緒和程序的區別:

1、執行緒是程序的一部分,所以執行緒有的時候被稱為是輕權程序或者輕量級程序。

2、一個沒有執行緒的程序是可以被看作單執行緒的,如果一個程序內擁有多個程序,程序的執行過程不是一條線(執行緒)的,而是多條線(執行緒)共同完成的。

3、系統在執行的時候會為每個程序分配不同的記憶體區域,但是不會為執行緒分配記憶體(執行緒所使用的資源是它所屬的程序的資源),執行緒組只能共享資源。那就是說,出了CPU之外(執行緒在執行的時候要佔用CPU資源),計算機內部的軟硬體資源的分配與執行緒無關,執行緒只能共享它所屬程序的資源。

4、與程序的控制表PCB相似,執行緒也有自己的控制表TCB,但是TCB中所儲存的執行緒狀態比PCB表中少多了。

5、程序是系統所有資源分配時候的一個基本單位,擁有一個完整的虛擬空間地址,並不依賴執行緒而獨立存在。

程序與程式的區別:

程式是一組指令的集合,它是靜態的實體,沒有執行的含義。而程序是一個動態的實體,有自己的生命週期。一般說來,一個程序肯定與一個程式相對應,並且只有一個,但是一個程式可以有多個程序,或者一個程序都沒有。除此之外,程序還有併發性和交往性。簡單地說,程序是程式的一部分,程式執行的時候會產生程序。

總結:

執行緒是程序的一部分,程序是程式的一部分