C/C++筆試題 (二)

12 . 下面的代碼輸出是什麼,爲什麼?

void foo(void)
{
    unsigned int a = 6;
    int b = -20;
    (a+b > 6) ? puts("> 6") : puts("<= 6");
}
這個問題測試你是否懂得C語言中的整數自動轉換原則,我發現有些開發者懂得極少這些東西。不管如何,這無符號整型問題的答案是輸出是 ">6"。原因是當表達式中存在有符號類型和無符號類型時所有的操作數都自動轉換爲無符號類型。因此-20變成了一個非常大的正整數,所以該表達式計算出的結果大於6。這一點對於應當頻繁用到無符號數據類型的嵌入式系統來說是豐常重要的。如果你答錯了這個問題,你也就到了得不到這份工作的邊緣。

13. 評價下面的代碼片斷:

unsigned int zero = 0;
unsigned int compzero = 0xFFFF; 
/*1's complement of zero */

對於一個int型不是16位的處理器爲說,上面的代碼是不正確的。應編寫如下:

unsigned int compzero = ~0;

這一問題真正能揭露出應試者是否懂得處理器字長的重要性。在我的經驗裏,好的嵌入式程序員非常準確地明白硬件的細節和它的侷限,然而PC機程序往往把硬件作爲一個無法避免的煩惱。
到了這個階段,應試者或者完全垂頭喪氣了或者信心滿滿志在必得。如果顯然應試者不是很好,那麼這個測試就在這裏結束了。但如果顯然應試者做得不錯,那麼我就扔出下面的追加問題,這些問題是比較難的,我想僅僅非常優秀的應試者能做得不錯。提出這些問題,我希望更多看到應試者應付問題的方法,而不是答案。不管如何,你就當是這個娛樂吧...

動態內存分配(Dynamic memory allocation)

14. 儘管不像非嵌入式計算機那麼常見,嵌入式系統還是有從堆(heap)中動態分配內存的過程的。那麼嵌入式系統中,動態分配內存可能發生的問題是什麼?
這裏,我期望應試者能提到內存碎片,碎片收集的問題,變量的持行時間等等。這個主題已經在ESP雜誌中被廣泛地討論過了(主要是 P.J. Plauger, 他的解釋遠遠超過我這裏能提到的任何解釋),所有回過頭看一下這些雜誌吧!讓應試者進入一種虛假的安全感覺後,我拿出這麼一個小節目:
下面的代碼片段的輸出是什麼,爲什麼?

char *ptr;
if ((ptr = (char *)malloc(0)) == NULL) 
    puts("Got a null pointer");
else
    puts("Got a valid pointer");

這是一個有趣的問題。最近在我的一個同事不經意把0值傳給了函數malloc,得到了一個合法的指針之後,我纔想到這個問題。這就是上面的代碼,該代碼的輸出是"Got a valid pointer"。我用這個來開始討論這樣的一問題,看看被面試者是否想到庫例程這樣做是正確。得到正確的答案固然重要,但解決問題的方法和你做決定的基本原理更重要些。

Typedef 

15 Typedef 在C語言中頻繁用以聲明一個已經存在的數據類型的同義字。也可以用預處理器做類似的事。例如,思考一下下面的例子:

#define dPS struct s *
typedef struct s * tPS;

以上兩種情況的意圖都是要定義dPS 和 tPS 作爲一個指向結構s指針。哪種方法更好呢?(如果有的話)爲什麼?
這是一個非常微妙的問題,任何人答對這個問題(正當的原因)是應當被恭喜的。答案是:typedef更好。思考下面的例子:

dPS p1,p2;
tPS p3,p4;

第一個擴展爲

struct s * p1, p2;
.
上面的代碼定義p1爲一個指向結構的指,p2爲一個實際的結構,這也許不是你想要的。第二個例子正確地定義了p3 和p4 兩個指針。晦澀的語法

16 . C語言同意一些令人震驚的結構,下面的結構是合法的嗎,如果是它做些什麼?

int a = 5, b = 7, c;
c = a+++b;

這個問題將做爲這個測驗的一個愉快的結尾。不管你相不相信,上面的例子是完全合乎語法的。問題是編譯器如何處理它?水平不高的編譯作者實際上會爭論這個問題,根據最處理原則,編譯器應當能處理儘可能所有合法的用法。因此,上面的代碼被處理成:

c = a++ + b;

因此, 這段代碼持行後a = 6, b = 7, c = 12。
如果你知道答案,或猜出正確答案,做得好。如果你不知道答案,我也不把這個當作問題。我發現這個問題的最大好處是這是一個關於代碼編寫風格,代碼的可讀性,代碼的可修改性的好的話題。

華爲筆試題 
1.寫出判斷ABCD四個表達式的是否正確, 若正確, 寫出經過表達式中 a的值(3分)
int a = 4;
(A)a += (a++); (B) a += (++a) ;(C) (a++) += a;(D) (++a) += (a++);
a = ?
答:C錯誤,左側不是一個有效變量,不能賦值,可改爲(++a) += a;
改後答案依次爲9,10,10,11

2.某32位系統下, C++程序,請計算sizeof 的值(5分).
char str[] = “http://www.ibegroup.com/”
char *p = str ;
int n = 10;
請計算
sizeof (str ) = ?(1)
sizeof ( p ) = ?(2)
sizeof ( n ) = ?(3)
void Foo ( char str[100]){
請計算
sizeof( str ) = ?(4)
}
void *p = malloc( 100 );
請計算
sizeof ( p ) = ?(5)
答:(1)17 (2)4 (3) 4 (4)4 (5)4

3. 回答下面的問題. (4分)
(1).頭文件中的 ifndef/define/endif 幹什麼用?預處理
答:防止頭文件被重複引用
(2). #i nclude 和 #i nclude “filename.h” 有什麼區別?
答:前者用來包含開發環境提供的庫頭文件,後者用來包含自己編寫的頭文件。
(3).在C++ 程序中調用被 C 編譯器編譯後的函數,爲什麼要加 extern “C”聲明?
答:函數和變量被C++編譯後在符號庫中的名字與C語言的不同,被extern "C"修飾的變
量和函數是按照C語言方式編譯和連接的。由於編譯後的名字不同,C++程序不能直接調
用C 函數。C++提供了一個C 連接交換指定符號extern“C”來解決這個問題。
(4). switch()中不允許的數據類型是?
答:實型

4. 回答下面的問題(6分)
(1).Void GetMemory(char **p, int num){
*p = (char *)malloc(num);
}
void Test(void){
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
請問運行Test 函數會有什麼樣的結果?
答:輸出“hello”
(2). void Test(void){
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL){
strcpy(str, “world”);
printf(str);
}
}
請問運行Test 函數會有什麼樣的結果?
答:輸出“world”
(3). char *GetMemory(void){
char p[] = "hello world";
return p;
}
void Test(void){
char *str = NULL;
str = GetMemory();
printf(str);
}
請問運行Test 函數會有什麼樣的結果?
答:無效的指針,輸出不確定

5. 編寫strcat函數(6分)
已知strcat函數的原型是char *strcat (char *strDest, const char *strSrc);
其中strDest 是目的字符串,strSrc 是源字符串。
(1)不調用C++/C 的字符串庫函數,請編寫函數 strcat
答:
VC源碼:
char * __cdecl strcat (char * dst, const char * src)
{
char * cp = dst;
while( *cp )
cp++; /* find end of dst */
while( *cp++ = *src++ ) ; /* Copy src to end of dst */
return( dst ); /* return dst */
}
(2)strcat能把strSrc 的內容連接到strDest,爲什麼還要char * 類型的返回值?
答:方便賦值給其他變量

6.MFC中CString是類型安全類麼?
答:不是,其它數據類型轉換到CString可以使用CString的成員函數Format來轉換

7.C++中爲什麼用模板類。
答:(1)可用來創建動態增長和減小的數據結構
(2)它是類型無關的,因此具有很高的可複用性。
(3)它在編譯時而不是運行時檢查數據類型,保證了類型安全
(4)它是平臺無關的,可移植性
(5)可用於基本數據類型

8.CSingleLock是幹什麼的。
答:同步多個線程對一個數據類的同時訪問

9.NEWTEXTMETRIC 是什麼。
答:物理字體結構,用來設置字體的高寬大小

10.程序什麼時候應該使用線程,什麼時候單線程效率高。
答:1.耗時的操作使用線程,提高應用程序響應
2.並行操作時使用線程,如C/S架構的服務器端併發線程響應用戶的請求。
3.多CPU系統中,使用線程提高CPU利用率
4.改善程序結構。一個既長又複雜的進程可以考慮分爲多個線程,成爲幾個獨立或半獨
立的運行部分,這樣的程序會利於理解和修改。
其他情況都使用單線程。

11.Windows是內核級線程麼。
答:見下一題

12.Linux有內核級線程麼。
答:線程通常被定義爲一個進程中代碼的不同執行路線。從實現方式上劃分,線程有兩
種類型:“用戶級線程”和“內核級線程”。 用戶線程指不需要內核支持而在用戶程序
中實現的線程,其不依賴於操作系統核心,應用進程利用線程庫提供創建、同步、調度
和管理線程的函數來控制用戶線程。這種線程甚至在象 DOS 這樣的操作系統中也可實現
,但線程的調度需要用戶程序完成,這有些類似 Windows 3.x 的協作式多任務。另外一
種則需要內核的參與,由內核完成線程的調度。其依賴於操作系統核心,由內核的內部
需求進行創建和撤銷,這兩種模型各有其好處和缺點。用戶線程不需要額外的內核開支
,並且用戶態線程的實現方式可以被定製或修改以適應特殊應用的要求,但是當一個線
程因 I/O 而處於等待狀態時,整個進程就會被調度程序切換爲等待狀態,其他線程得不
到運行的機會;而內核線程則沒有各個限制,有利於發揮多處理器的併發優勢,但卻佔
用了更多的系統開支。 
Windows NT和OS/2支持內核線程。Linux 支持內核級的多線程

13.C++中什麼數據分配在棧或堆中,New分配數據是在近堆還是遠堆中?
答:棧: 存放局部變量,函數調用參數,函數返回值,函數返回地址。由系統管理
堆: 程序運行時動態申請,new 和 malloc申請的內存就在堆上

14.使用線程是如何防止出現大的波峯。
答:意思是如何防止同時產生大量的線程,方法是使用線程池,線程池具有可以同時提
高調度效率和限制資源使用的好處,線程池中的線程達到最大數時,其他線程就會排隊
等候。

15函數模板與類模板有什麼區別?
答:函數模板的實例化是由編譯程序在處理函數調用時自動完成的,而類模板的實例化
必須由程序員在程序中顯式地指定。

16一般數據庫若出現日誌滿了,會出現什麼情況,是否還能使用?
答:只能執行查詢等讀操作,不能執行更改,備份等寫操作,原因是任何寫操作都要記
錄日誌。也就是說基本上處於不能使用的狀態。

17 SQL Server是否支持行級鎖,有什麼好處?
答:支持,設立封鎖機制主要是爲了對併發操作進行控制,對干擾進行封鎖,保證數據
的一致性和準確性,行級封鎖確保在用戶取得被更新的行到該行進行更新這段時間內不
被其它用戶所修改。因而行級鎖即可保證數據的一致性又能提高數據操作的迸發性。

18如果數據庫滿了會出現什麼情況,是否還能使用?
答:見16

19 關於內存對齊的問題以及sizof()的輸出 
答:編譯器自動對齊的原因:爲了提高程序的性能,數據結構(尤其是棧)應該儘可能
地在自然邊界上對齊。原因在於,爲了訪問未對齊的內存,處理器需要作兩次內存訪問
;然而,對齊的內存訪問僅需要一次訪問。

20 int i=10, j=10, k=3; k*=i+j; k最後的值是?
答:60,此題考察優先級,實際寫成: k*=(i+j);,賦值運算符優先級最低

21.對數據庫的一張表進行操作,同時要對另一張表進行操作,如何實現?
答:將操作多個表的操作放入到事務中進行處理

22.TCP/IP 建立連接的過程?(3-way shake)
答:在TCP/IP協議中,TCP協議提供可靠的連接服務,採用三次握手建立一個連接。
  第一次握手:建立連接時,客戶端發送syn包(syn=j)到服務器,並進入SYN_SEND狀
態,等待服務器確認;
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個
SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
  第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1)
,此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。

23.ICMP是什麼協議,處於哪一層?
答:Internet控制報文協議,處於網絡層(IP層)

24.觸發器怎麼工作的?
答:觸發器主要是通過事件進行觸發而被執行的,當對某一表進行諸如UPDATE、 INSERT
、 DELETE 這些操作時,數據庫就會自動執行觸發器所定義的SQL 語句,從而確保對數
據的處理必須符合由這些SQL 語句所定義的規則。

25.winsock建立連接的主要實現步驟?
答:服務器端:socker()建立套接字,綁定(bind)並監聽(listen),用accept()
等待客戶端連接。
客戶端:socker()建立套接字,連接(connect)服務器,連接上後使用send()和recv(
),在套接字上寫讀數據,直至數據交換完畢,closesocket()關閉套接字。
服務器端:accept()發現有客戶端連接,建立一個新的套接字,自身重新開始等待連
接。該新產生的套接字使用send()和recv()寫讀數據,直至數據交換完畢,closesock
et()關閉套接字。

26.動態連接庫的兩種方式?
答:調用一個DLL中的函數有兩種方法:
1.載入時動態鏈接(load-time dynamic linking),模塊非常明確調用某個導出函數
,使得他們就像本地函數一樣。這需要鏈接時鏈接那些函數所在DLL的導入庫,導入庫向
系統提供了載入DLL時所需的信息及DLL函數定位。 
2.運行時動態鏈接(run-time dynamic linking),運行時可以通過LoadLibrary或Loa
dLibraryEx函數載入DLL。DLL載入後,模塊可以通過調用GetProcAddress獲取DLL函數的
出口地址,然後就可以通過返回的函數指針調用DLL函數了。如此即可避免導入庫文件了

27.IP組播有那些好處?
答:Internet上產生的許多新的應用,特別是高帶寬的多媒體應用,帶來了帶寬的急劇
消耗和網絡擁擠問題。組播是一種允許一個或多個發送者(組播源)發送單一的數據包
到多個接收者(一次的,同時的)的網絡技術。組播可以大大的節省網絡帶寬,因爲無
論有多少個目標地址,在整個網絡的任何一條鏈路上只傳送單一的數據包。所以說組播
技術的核心就是針對如何節約網絡資源的前提下保證服務質量。

1.static有什麼用途?(請至少說明兩種)
    1)在函數體,一個被聲明爲靜態的變量在這一函數被調用過程中維持其值不變。
    2) 在模塊內(但在函數體外),一個被聲明爲靜態的變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變量。
    3) 在模塊內,一個被聲明爲靜態的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地範圍內使用

2.引用與指針有什麼區別?
    1) 引用必須被初始化,指針不必。
    2) 引用初始化以後不能被改變,指針可以改變所指的對象。
    3) 不存在指向空值的引用,但是存在指向空值的指針。

3.描述實時系統的基本特性
       在特定時間內完成特定的任務,實時性與可靠性。

4.全局變量和局部變量在內存中是否有區別?如果有,是什麼區別?
      全局變量儲存在靜態數據庫,局部變量在堆棧。

5.什麼是平衡二叉樹?
      左右子樹都是平衡二叉樹 且左右子樹的深度差值的絕對值不大於1。

6.堆棧溢出一般是由什麼原因導致的?
      沒有回收垃圾資源。

7.什麼函數不能聲明爲虛函數?
      constructor函數不能聲明爲虛函數。

8.冒泡排序算法的時間複雜度是什麼?
      時間複雜度是O(n^2)。

9.寫出float x 與“零值”比較的if語句。
      if(x>0.000001&&x<-0.000001)

10.Internet採用哪種網絡協議?該協議的主要層次結構?
      Tcp/Ip協議
      主要層次結構爲: 應用層/傳輸層/網絡層/數據鏈路層/物理層。

11.Internet物理地址和IP地址轉換採用什麼協議?
      ARP (Address Resolution Protocol)(地址解析協議)

12.IP地址的編碼分爲哪倆部分?
     IP地址由兩部分組成,網絡號和主機號。不過是要和“子網掩碼”按位與上之後才能區分哪些是網絡位哪些是主機位。

13.用戶輸入M,N值,從1至N開始順序循環數數,每數到M輸出該數值,直至全部輸出。寫出C程序。
     循環鏈表,用取餘操作做
14.不能做switch()的參數類型是:
     switch的參數不能爲實型。

華為
1、局部變量能否和全局變量重名?
     答:能,局部會屏蔽全局。要用全局變量,需要使用"::"
局部變量可以與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。對於有些編譯器而言,在同一個函數內可以定義多個同名的局部變量,比如在兩個循環體內都定義一個同名的局部變量,而那個局部變量的作用域就在那個循環體內。

2、如何引用一個已經定義過的全局變量?
     答:extern
     可以用引用頭文件的方式,也可以用extern關鍵字,如果用引用頭文件方式來引用某個在頭文件中聲明的全局變理,假定你將那個變寫錯了,那麼在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那麼在編譯期間不會報錯,而在連接期間報錯。

3、全局變量可不可以定義在可被多個.C文件包含的頭文件中?爲什麼?
    答:可以,在不同的C文件中以static形式來聲明同名全局變量。
    可以在不同的C文件中聲明同名的全局變量,前提是其中只能有一個C文件中對此變量賦初值,此時連接不會出錯。

4、語句for( ;1 ;)有什麼問題?它是什麼意思?
    答:無限循環,和while(1)相同。

5、do……while和while……do有什麼區別?
    答:前一個循環一遍再判斷,後一個判斷以後再循環。

6、請寫出下列代碼的輸出內容
#i nclude<stdio.h>
main()
{
int a,b,c,d;
a=10;
b=a++;
c=++a;
d=10*a++;
printf("b,c,d:%d,%d,%d",b,c,d);
return 0;

答:10,12,120

1、static全局變量與普通的全局變量有什麼區別?static局部變量和普通局部變量有什麼區別?static函數與普通函數有什麼區別?
    答:全局變量(外部變量)的說明之前再冠以static 就構成了靜態的全局變量。全局變量本身就是靜態存儲方式, 靜態全局變量當然也是靜態存儲方式。 這兩者在存儲方式上並無不同。這兩者的區別雖在於非靜態全局變量的作用域是整個源程序, 當一個源程序由多個源文件組成時,非靜態的全局變量在各個源文件中都是有效的。 而靜態全局變量則限制了其作用域, 即只在定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。由於靜態全局變量的作用域侷限於一個源文件內,只能爲該源文件內的函數公用, 因此可以避免在其它源文件中引起錯誤。
    從以上分析可以看出, 把局部變量改變爲靜態變量後是改變了它的存儲方式即改變了它的生存期。把全局變量改變爲靜態變量後是改變了它的作用域, 限制了它的使用範圍。
    static函數與普通函數作用域不同。僅在本文件。只在當前源文件中使用的函數應該說明爲內部函數(static),內部函數應該在當前源文件中說明和定義。對於可在當前源文件以外使用的函數,應該在一個頭文件中說明,要使用這些函數的源文件要包含這個頭文件
    static全局變量與普通的全局變量有什麼區別:static全局變量只初使化一次,防止在其他文件單元中被引用;
    static局部變量和普通局部變量有什麼區別:static局部變量只被初始化一次,下一次依據上一次結果值;
    static函數與普通函數有什麼區別:static函數在內存中只有一份,普通函數在每個被調用中維持一份拷貝

2、程序的局部變量存在於(堆棧)中,全局變量存在於(靜態區 )中,動態申請數據存在於( 堆)中。

3、設有以下說明和定義:
typedef union {long i; int k[5]; char c;} DATE;
struct data { int cat; DATE cow; double dog;} too;
DATE max;
則語句 printf("%d",sizeof(struct date)+sizeof(max));的執行結果是:___52____
    答:DATE是一個union, 變量公用空間. 裏面最大的變量類型是int[5], 佔用20個字節. 所以它的大小是20
data是一個struct, 每個變量分開佔用空間. 依次爲int4 + DATE20 + double8 = 32.
所以結果是 20 + 32 = 52.
當然...在某些16位編輯器下, int可能是2字節,那麼結果是 int2 + DATE10 + double8 = 20

4、隊列和棧有什麼區別?
    隊列先進先出,棧後進先出

5、寫出下列代碼的輸出內容
#i nclude<stdio.h>
int inc(int a)
{
return(++a);
}
int multi(int*a,int*b,int*c)
{
return(*c=*a**b);
}
typedef int(FUNC1)(int in);
typedef int(FUNC2) (int*,int*,int*);

void show(FUNC2 fun,int arg1, int*arg2)
{
INCp=&inc;
int temp =p(arg1);
fun(&temp,&arg1, arg2);
printf("%d\n",*arg2);
}

main()
{
int a;
show(multi,10,&a);
return 0;
}
答:110
7、請找出下面代碼中的所以錯誤
說明:以下代碼是把一個字符串倒序,如“abcd”倒序後變爲“dcba”

1、#i nclude"string.h"
2、main()
3、{
4、 char*src="hello,world";
5、 char* dest=NULL;
6、 int len=strlen(src);
7、 dest=(char*)malloc(len);
8、 char* d=dest;
9、 char* s=src[len];
10、 while(len--!=0) 
11、 d++=s--;
12、 printf("%s",dest);
13、 return 0;
14、} 
答:
方法1:
int main(){
char* src = "hello,world";
int len = strlen(src);
char* dest = (char*)malloc(len+1);//要爲\0分配一個空間
char* d = dest;
char* s = &src[len-1];//指向最後一個字符
while( len-- != 0 )
*d++=*s--;
*d = 0;//尾部要加\0
printf("%s\n",dest);
free(dest);// 使用完,應當釋放空間,以免造成內存匯泄露
return 0;
}
方法2:
#i nclude <stdio.h>
#i nclude <string.h>
main()
{
char str[]="hello,world";
int len=strlen(str);
char t;
for(int i=0; i<len/2; i++)
{
t=str[i]; 
str[i]=str[len-i-1]; str[len-i-1]=t;
}
printf("%s",str);
return 0;
}
1.-1,2,7,28,,126請問28和126中間那個數是什麼?爲什麼?
第一題的答案應該是4^3-1=63
規律是n^3-1(當n爲偶數0,2,4)
      n^3+1(當n爲奇數1,3,5)
答案:63
2.用兩個棧實現一個隊列的功能?要求給出算法和思路!
設2個棧爲A,B, 一開始均爲空.

入隊:
將新元素push入棧A;

出隊:
(1)判斷棧B是否爲空;
(2)如果不爲空,則將棧A中所有元素依次pop出並push到棧B;
(3)將棧B的棧頂元素pop出;

這樣實現的隊列入隊和出隊的平攤複雜度都還是O(1), 比上面的幾種方法要好。3.在c語言庫函數中將一個字符轉換成整型的函數是atool()嗎,這個函數的原型是什麼?
函數名: atol 
功 能: 把字符串轉換成長整型數 
用 法: long atol(const char *nptr); 
程序例: 
#i nclude <stdlib.h> 
#i nclude <stdio.h> 
int main(void) 

long l; 
char *str = "98765432";

l = atol(lstr); 
printf("string = %s integer = %ld\n", str, l); 
return(0); 
}

2.對於一個頻繁使用的短小函數,在C語言中應用什麼實現,在C++中應用什麼實現?
c用宏定義,c++用inline
3.直接鏈接兩個信令點的一組鏈路稱作什麼?
PPP點到點連接
4.接入網用的是什麼接口?
5.voip都用了那些協議?
6.軟件測試都有那些種類?
黑盒:針對系統功能的測試    白合:測試函數功能,各函數接口
7.確定模塊的功能和模塊的接口是在軟件設計的那個隊段完成的?
概要設計階段
8.enum string
    {
    x1,
    x2,
    x3=10,
    x4,
    x5,
    }x;
   問x= 0x801005,0x8010f4 ;
9.unsigned char *p1;
    unsigned long *p2;
    p1=(unsigned char *)0x801000;
    p2=(unsigned long *)0x810000;
    請問p1+5= ;
        p2+5= ;
三.選擇題:
1.Ethternet鏈接到Internet用到以下那個協議?
A.HDLC;B.ARP;C.UDP;D.TCP;E.ID
2.屬於網絡層協議的是:
A.TCP;B.IP;C.ICMP;D.X.25
3.Windows消息調度機制是:
A.指令隊列;B.指令堆棧;C.消息隊列;D.消息堆棧;
4.unsigned short hash(unsigned short key)
    {
      return (key>>)%256
    }
   請問hash(16),hash(256)的值分別是:
A.1.16;B.8.32;C.4.16;D.1.32
四.找錯題:
1.請問下面程序有什麼錯誤?
   int a[60][250][1000],i,j,k;
   for(k=0;k<=1000;k++)
    for(j=0;j<250;j++)
     for(i=0;i<60;i++)
      a[i][j][k]=0;
把循環語句內外換一下
2.#define Max_CB 500
    void LmiQueryCSmd(Struct MSgCB * pmsg)
     {
     unsigned char ucCmdNum;
     ......
    
     for(ucCmdNum=0;ucCmdNum<Max_CB;ucCmdNum++)
      {
      ......;
      }
死循環
   3.以下是求一個數的平方的程序,請找出錯誤:
    #define SQUARE(a)((a)*(a))
    int a=5;
    int b;
    b=SQUARE(a++);
   4.typedef unsigned char BYTE
     int examply_fun(BYTE gt_len; BYTE *gt_code)
      { 
      BYTE *gt_buf;
      gt_buf=(BYTE *)MALLOC(Max_GT_Length);
      ......
      if(gt_len>Max_GT_Length)
        {
        return GT_Length_ERROR; 
        }
        .......
      }
五.問答題:
   1.IP Phone的原理是什麼?
IPV6
   2.TCP/IP通信建立的過程怎樣,端口有什麼作用?
三次握手,確定是哪個應用程序使用該協議
   3.1號信令和7號信令有什麼區別,我國某前廣泛使用的是那一種?
   4.列舉5種以上的電話新業務?

微軟亞洲技術中心的面試題!!!
1.進程和線程的差別。
線程是指進程內的一個執行單元,也是進程內的可調度實體.
與進程的區別:
(1)調度:線程作爲調度和分配的基本單位,進程作爲擁有資源的基本單位
(2)併發性:不僅進程之間可以併發執行,同一個進程的多個線程之間也可併發執行
(3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但可以訪問隸屬於進程的資源. 
(4)系統開銷:在創建或撤消進程時,由於系統都要爲之分配和回收資源,導致系統的開銷明顯大於創建或撤消線程時的開銷。
2.測試方法 
人工測試:個人複查、抽查和會審
機器測試:黑盒測試和白盒測試

2.Heap與stack的差別。
Heap是堆,stack是棧。
Stack的空間由操作系統自動分配/釋放,Heap上的空間手動分配/釋放。
Stack空間有限,Heap是很大的自由存儲區
C中的malloc函數分配的內存空間即在堆上,C++中對應的是new操作符。
程序在編譯期對變量和函數分配內存都在棧上進行,且程序運行過程中函數調用時參數的傳遞也在棧上進行
3.Windows下的內存是如何管理的?
4.介紹.Net和.Net的安全性。
5.客戶端如何訪問.Net組件實現Web Service?
6.C/C++編譯器中虛表是如何完成的?
7.談談COM的線程模型。然後討論進程內/外組件的差別。
8.談談IA32下的分頁機制
小頁(4K)兩級分頁模式,大頁(4M)一級
9.給兩個變量,如何找出一個帶環單鏈表中是什麼地方出現環的?
一個遞增一,一個遞增二,他們指向同一個接點時就是環出現的地方
10.在IA32中一共有多少種辦法從用戶態跳到內核態?
通過調用門,從ring3到ring0,中斷從ring3到ring0,進入vm86等等
11.如果只想讓程序有一個實例運行,不能運行兩個。像winamp一樣,只能開一個窗口,怎樣實現?
用內存映射或全局原子(互斥變量)、查找窗口句柄.. 
FindWindow,互斥,寫標誌到文件或註冊表,共享內存。.  
12.如何截取鍵盤的響應,讓所有的‘a’變成‘b’?
鍵盤鉤子SetWindowsHookEx
 13.Apartment在COM中有什麼用?爲什麼要引入?
 14.存儲過程是什麼?有什麼用?有什麼優點?
我的理解就是一堆sql的集合,可以建立非常複雜的查詢,編譯運行,所以運行一次後,以後再運行速度比單獨執行SQL快很多
 15.Template有什麼特點?什麼時候用?
16.談談Windows DNA結構的特點和優點。


網絡編程中設計併發服務器,使用多進程 與 多線程 ,請問有什麼區別?
1,進程:子進程是父進程的複製品。子進程獲得父進程數據空間、堆和棧的複製品。
2,線程:相對與進程而言,線程是一個更加接近與執行體的概念,它可以與同進程的其他線程共享數據,但擁有自己的棧空間,擁有獨立的執行序列。
兩者都可以提高程序的併發度,提高程序運行效率和響應時間。
線程和進程在使用上各有優缺點:線程執行開銷小,但不利於資源管理和保護;而進程正相反。同時,線程適合於在SMP機器上運行,而進程則可以跨機器遷移。

思科
1. 用宏定義寫出swap(x,y)
#define swap(x, y)\
x = x + y;\
y = x - y;\
x = x - y;
2.數組a[N],存放了1至N-1個數,其中某個數重複一次。寫一個函數,找出被重複的數字.時間複雜度必須爲o(N)函數原型:
int do_dup(int a[],int N)
3 一語句實現x是否爲2的若干次冪的判斷
int i = 512;
cout << boolalpha << ((i & (i - 1)) ? false : true) << endl;
4.unsigned int intvert(unsigned int x,int p,int n)實現對x的進行轉換,p爲起始轉化位,n爲需要轉換的長度,假設起始點在右邊.如x=0b0001 0001,p=4,n=3轉換後x=0b0110 0001
unsigned int intvert(unsigned int x,int p,int n){
unsigned int _t = 0;
unsigned int _a = 1;
for(int i = 0; i < n; ++i){
_t |= _a;
_a = _a << 1;
}
_t = _t << p;
x ^= _t;
return x;
}

慧通:
什麼是預編譯
何時需要預編譯:
1、總是使用不經常改動的大型代碼體。 
2、程序由多個模塊組成,所有模塊都使用一組標準的包含文件和相同的編譯選項。在這種情況下,可以將所有包含文件預編譯爲一個預編譯頭。
char * const p;
char const * p
const char *p

上述三個有什麼區別?
char * const p; //常量指針,p的值不可以修改
char const * p;//指向常量的指針,指向的常量值不可以改
const char *p; //和char const *p

char str1[] = "abc";
char str2[] = "abc";

const char str3[] = "abc";
const char str4[] = "abc";

const char *str5 = "abc";
const char *str6 = "abc";

char *str7 = "abc";
char *str8 = "abc";


cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;

結果是:0 0 1 1
解答:str1,str2,str3,str4是數組變量,它們有各自的內存空間;
而str5,str6,str7,str8是指針,它們指向相同的常量區域。


12. 以下代碼中的兩個sizeof用法有問題嗎?[C易]
void UpperCase( char str[] ) // 將 str 中的小寫字母轉換成大寫字母
{
    for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )
        if( 'a'<=str[i] && str[i]<='z' )
            str[i] -= ('a'-'A' );
}
char str[] = "aBcDe";
cout << "str字符長度爲: " << sizeof(str)/sizeof(str[0]) << endl;
UpperCase( str );
cout << str << endl;

答:函數內的sizeof有問題。根據語法,sizeof如用於數組,只能測出靜態數組的大小,無法檢測動態分配的或外部數組大小。函數外的str是一個靜態定義的數組,因此其大小爲6,函數內的str實際只是一個指向字符串的指針,沒有任何額外的與數組相關的信息,因此sizeof作用於上只將其當指針看,一個指針爲4個字節,因此返回4。

一個32位的機器,該機器的指針是多少位
指針是多少位只要看地址總線的位數就行了。80386以後的機子都是32的數據總線。所以指針的位數就是4個字節了。

main()
{
int a[5]={1,2,3,4,5};
   int *ptr=(int *)(&a+1);

   printf("%d,%d",*(a+1),*(ptr-1));
}
輸出:2,5
*(a+1)就是a[1],*(ptr-1)就是a[4],執行結果是2,5
&a+1不是首地址+1,系統會認爲加一個a數組的偏移,是偏移了一個數組的大小(本例是5個int)
int *ptr=(int *)(&a+1); 
則ptr實際是&(a[5]),也就是a+5
原因如下:
&a是數組指針,其類型爲 int (*)[5];
而指針加1要根據指針類型加上一定的值,
不同類型的指針+1之後增加的大小不同
a是長度爲5的int數組指針,所以要加 5*sizeof(int)
所以ptr實際是a[5]
但是prt與(&a+1)類型是不一樣的(這點很重要)
所以prt-1只會減去sizeof(int*)
a,&a的地址是一樣的,但意思不一樣,a是數組首地址,也就是a[0]的地址,&a是對象(數組)首地址,a+1是數組下一元素的地址,即a[1],&a+1是下一個對象的地址,即a[5].


1.請問以下代碼有什麼問題:
int main()
{
char a;
char *str=&a;
strcpy(str,"hello");
printf(str);
return 0;
}
沒有爲str分配內存空間,將會發生異常
問題出在將一個字符串複製進一個字符變量指針所指地址。雖然可以正確輸出結果,但因爲越界進行內在讀寫而導致程序崩潰。

char* s="AAA";
printf("%s",s);
s[0]='B';
printf("%s",s);
有什麼錯?
"AAA"是字符串常量。s是指針,指向這個字符串常量,所以聲明s的時候就有問題。
cosnt char* s="AAA";
然後又因爲是常量,所以對是s[0]的賦值操作是不合法的。

發佈了25 篇原創文章 · 獲贊 4 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章