名企招聘C 程序員筆試題_第1頁
名企招聘C 程序員筆試題_第2頁
名企招聘C 程序員筆試題_第3頁
名企招聘C 程序員筆試題_第4頁
名企招聘C 程序員筆試題_第5頁
已閱讀5頁,還剩34頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

(―)

單向鏈表的反轉是?個經常被問到的?個面試題,也是?個非常基礎的問

題。比如一個鏈表是這樣的:1->2-〉3->4->5通過反轉后成為5->4->3->2-〉1。

最容易想到的方法遍歷一遍鏈表,利用一個輔助指針,存儲遍歷過程中當前

指針指向的下?個元素,然后將當前節點元素的指針反轉后,利用已經存儲的指

針往后面繼續遍歷。源代碼如下:

structlinka{

intdata;

linka*next;

);

voidreverse(linka*&head){

if(head二二NULL)

return;

linka*pre,*cur,*ne;

pre=head;

cur=head->next;

while(cur)

I

ne=cur->next;

cur->next=pre;

pre=cur;

cur=ne;

)

head->next=NULL;

head=pre;

}

還有種利用遞歸的方法。這種方法的基本思想是在反轉當前節點之前先調

用遞歸函數反轉后續節點。源代碼如下。不過這個方法有一個缺點,就是在反轉

后的最后個結點會形成一個環,所以必須將函數的返回的節點的next域置為

NULL0因為要改變head指針,所以我用了引用。算法的源代碼如下:

linka*reverse(linka*p,linka*&head)

if(p==NULL||p->next==NULL)

{

head=p;

returnp;

)

else

{

linka*tmp=reverse(p->next,head);

tmp->next=p;

returnp;

)

)

②已知String類定義如下:

classString

{

public:

String(constchar*str=NULL);//通用構造函數

String(constStringfeanother);//拷貝構造函數

~StringO;//析構函數

String&operator=(constString&rhs);//賦值函數

private:

char*m_data;//用于保存字符串

);

嘗試寫出類的成員函數實現。

答案:

String::String(constchar*str)

{

if(str==NULL)〃strlen在參數為NULL時會拋異常才會有這步判斷

m_data=newchar[1]

m_data[O]=;

)

else

{

m_data=newchar[strlen(str)+1];

strcpy(m_data,str);

)

)

String::String(constString&another)

(

m_data=newchar[strlen(another.m_data)+1];

strcpy(m_data,other,m_data);

)

StringfeString::operator=(constString&rhs)

(

if(this==&rhs)

return*this;

delete[]m_data;〃刪除原來的數據,新開一塊內存

m_data=newchar[strlen(rhs.m_data)+1];

strcpy(mdata,rhs.mdata);

return*this;

)

String::^String()

(

delete[]m_data;

)

L求下面函數的返回值(微軟)

intfunc(x)

intcountx=0;

while(x)

countx++;

x=x&(xT);

returncountx;

假定x=9999o答案:8

思路:將x轉化為2進制,看含有的1的個數。

2.什么是“引用”?申明和使用“引用”要注意哪些問題?

答:引用就是某個目標變量的“別名”(alias),對應用的操作與對變量直

接操作效果完全相同。申明一個引用的時候,切記要對其進行初始化。引用聲明

完畢后,相當于目標變量名有兩個名稱,即該目標原名稱和引用名,不能再把該

引用名作為其他變量名的別名。聲明一個引用,不是新定義了一個變量,它只表

示該引用名是目標變量名的?個別名,它本身不是i種數據類型,因此引用本身

不占存儲單元,系統也不給引用分配存儲單元。不能建立數組的引用。

3.將“引用”作為函數參數有哪些特點?

(1)傳遞引用給函數與傳遞指針的效果是一樣的。這時,被調函數的形參就

成為原來主調函數中的實參變量或對象的一個別名來使用,所以在被調函數中對

形參變量的操作就是對其相應的目標對象(在主調函數中)的操作。

(2)使用引用傳遞函數的參數,在內存中并沒有產生實參的副本,它是直接

對實參操作;而使用一般變量傳遞函數的參數,當發生函數調用時,需要給形參

分配存儲單元,形參變量是實參變量的副本;如果傳遞的是對象,還將調用拷貝

構造函數。因此,當參數傳遞的數據較大時,用引用比用一般變量傳遞參數的效

率和所占空間都好。

(3)使用指針作為函數的參數雖然也能達到與使用引用的效果,但是,在被調

函數中同樣要給形參分配存儲單元,且需要重復使用“*指針變量名''的形式進行

運算,這很容易產生錯誤且程序的閱讀性較差;另方面,在主調函數的調用點

處,必須用變量的地址作為實參。而引用更容易使用,更清晰。

4.在什么時候需要使用“常引用”?

如果既要利用引用提高程序的效率,又要保護傳遞給函數的數據不在函數中

被改變,就應使用常引用。常引用聲明方式:const類型標識符&引用名=目標

變量名;

例1

inta;

constint&ra=a;

ra=l;〃錯誤

a=l;〃正確

例2

stringfoo();

voidbar(string&s);

那么下面的表達式將是非法的:

bar(foo());

bar(z/helloworld");

原因在于foo()和"helloworld”串都會產生一個臨時對象,而在C++中,

這些臨時對象都是const類型的。因此上面的表達式就是試圖將一個const類型

的對象轉換為非const類型,這是非法的。

引用型參數應該在能被定義為const的情況下,盡量定義為const。

5.將“引用”作為函數返回值類型的格式、好處和需要遵守的規則?

格式:類型標識符&函數名(形參列表及類型說明){〃函數體}

好處:在內存中不產生被返回值的副本;(注意:正是因為這點原因,所以返

回一個局部變量的引用是不可取的。因為隨著該局部變量生存期的結束,相應的

引用也會失效,產生runtimeerror!

注意事項:

(1)不能返回局部變量的引用。這條可以參照EffectiveC++[l]的Item31o

主要原因是局部變量會在函數返回后被銷毀,因此被返回的引用就成為了〃無所

指''的引用,程序會進入未知狀態。

(2)不能返回函數內部new分配的內存的引用。這條可以參照EffectiveC+

+[1]的八00)31。雖然不存在局部變量的被動銷毀問題,可對于這種情況(返回

函數內部new分配內存的引用),又面臨其它尷尬局面。例如,被函數返回的引

用只是作為一個臨時變量出現,而沒有被賦予一個實際的變量,那么這個引用所

指向的空間(由new分配)就無法釋放,造成memoryleako

(3)可以返回類成員的引用,但最好是const。這條原則可以參照Effectiv

eC++[l]的Item300主要原因是當對象的屬性是與某種業務規則(businessru

le)相關聯的時候,其賦值常常與某些其它屬性或者對象的狀態有關,因此有必

要將賦值操作封裝在一個業務規則當中。如果其它對象可以獲得該屬性的非常量

引用(或指針),那么對該屬性的單純賦值就會破壞業務規則的完整性。

(4)流操作符重載返回值申明為“引用”的作用:

流操作符<〈和>〉,這兩個操作符常常希望被連續使用,例如:cout?"he

llo,z?endl;因此這兩個操作符的返回值應該是一個仍然支持這兩個操作符

的流引用。可選的其它方案包括:返回一個流對象和返回個流對象指針。但是

對于返回一個流對象,程序必須重新(拷貝)構造一個新的流對象,也就是說,連

續的兩個〈〈操作符實際上是針對不同對象的!這無法讓人接受。對于返回個流

指針則不能連續使用"操作符。因此,返回一個流對象引用是惟一選擇。這個唯

?選擇很關鍵,它說明了引用的重要性以及無可替代性,也許這就是C++語言中

引入引用這個概念的原因吧。賦值操作符?這個操作符象流操作符一樣,是可

以連續使用的,例如:x=j=10;或者(x=10)=100;賦值操作符的返回值必須是

一個左值,以便可以被繼續賦值。因此引用成了這個操作符的惟一返回值選擇。

例3

#include

int&put(intn);

intvals[10]:

interror=-l;

voidmain()

put(0)=10;〃以put(0)函數值作為左值,等價于vals[0]=10;

put(9)=20;〃以put(9)函數值作為左值,等價于vals[9]=20;

cout

int&put(intn)

if(n>=0&&n<=9)returnvals[n];

else{cout?z/subscripterror”;returnerror;}

)

(5)在另外的一些操作符中,卻千萬不能返回引用:+-*/四則運算符。它們

不能返回引用,EffectiveC++[l]的Item23詳細的討論了這個問題。主要原因

是這四個操作符沒有sideeffect,因此,它們必須構造一個對象作為返回值,

可選的方案包括:返回個對象、返回一個局部變量的引用,返回一個new分配

的對象的引用、返回一個靜態對象引用。根據前面提到的引用作為返回值的三個

規則,第2、3兩個方案都被否決了。靜態對象的引用又因為((a+b)==(c+d))

會永遠為true而導致錯誤。所以可選的只剩下返回一個對象了。

6.“引用”與多態的關系?

引用是除指針外另一個可以產生多態效果的手段。這意味著,一個基類的引

用可以指向它的派生類實例。

例4

ClassA;ClassB:ClassA{...};Bb;A&ref=b;

7.“引用”與指針的區別是什么?

指針通過某個指針變量指向一個對象后,對它所指向的變量間接操作。程序

中使用指針,程序的可讀性差;而引用本身就是目標變量的別名,對引用的操作

就是對目標變量的操作。此外,就是上面提到的對函數傳ref和pointer的區別。

8.什么時候需要“引用”?

流操作符<<和>>、賦值操作符=的返回值、拷貝構造函數的參數、賦值操作

符=的參數、其它情況都推薦使用引用。

以上2-8參考:http://blog.csdn.net/wfwd/archive/2006/05/30/76355

1.aspx

9.結構與聯合有和區別?

1.結構和聯合都是由多個不同的數據類型成員組成,但在任何同一時刻,

聯合中只存放了一個被選中的成員(所有成員共用一塊地址空間),而結構的所

有成員都存在(不同成員的存放地址不同)。

2.對于聯合的不同成員賦值,將會對其它成員重寫,原來成員的值就不存

在了,而對于結構的不同成員賦值是互不影響的。

10.下面關于“聯合”的題目的輸出?

a)

#include

union

(

inti;

charx[2];

}a:

voidmain()

4

a.x[0]=10;

a.x[l]=1;

printf('%d”,a.i);

)

答案:266(低位低地址,高位高地址,內存占用情況是0x010A)

b)

main()

union{/*定義-個聯合*/

inti;

struct{/*在聯合中定義?個結構*/

charfirst;

charsecond;

}half;

}number;

number,i=0x4241;/*聯合成員賦值*/

printfCz%c%c,z,number.half,first,mumber.half,second);

number,half,first='a';/*聯合中結構成員賦值*/

number.half,second='b';

printf(zz%xz,,number,i);

getch();

)

答案:AB(0x41對應'A',是低位;0x42對應'B',是高位)

6261(number,i和number,half共用,塊地址空間)

11.已知strcpy的函數原型:char*strcpy(char*strDest,constchar

*strSrc)其中strDest是目的字符串,strSrc是源字符串。不調用C++/C的字

符串庫函數,請編寫函數strcpyo

答案:

char*strcpy(char*strDest,constchar*strSrc)

(

if(strDest==NULL||strSrc==NULL)

returnNULL;

if(strDest==strSrc)

returnstrDest;

char*tempptr=strDest;

while((*strDest++=*strSrc++)!='')

returntempptr;

12.已知String類定義如下:

classString

(

public:

String(constchar*str=NULL);//通用構造函數

String(constStringfeanother);//拷貝構造函數

~StringO;//析構函數

String&operator=(constString&rhs);//賦值函數

private:

char*m_data;//用于保存字符串

);

嘗試寫出類的成員函數實現。

答案:

String::String(constchar*str)

(

if(str==NULL)〃strlen在參數為NULL時會拋異常才會有這步判斷

(

m_data=newchar[1];

m_data[0]=;

}

else

(

m_data=newcharEstrlen(str)+1];

strcpy(m_data,str);

)

)

String::String(constString&another)

{

m_data=newchar[strlen(another.m_data)+1];

strcpy(m_data,other.m_data);

String&String::operator=(constString&rhs)

if(this==&rhs)

return*this;

delete[]m_data;〃刪除原來的數據,新開一塊內存

m_data=newchar[strlen(rhs.mdata)+1];

strcpy(m_data,rhs.m_data);

return*this;

)

String::"String()

delete[]m_data;

13..h頭文件中的ifndef/define/endif的作用?

答:防止該頭文件被重復引用。

14.#include與#include"file,h”的區別?

答:前者是從StandardLibrary的路徑尋找和引用file,h,而后者是從當前工

作路徑搜尋并引用file,h。

15.在C++程序中調用被C編譯器編譯后的函數,為什么要加extern"C”?

首先,作為extern是C/C++語言中表明函數和全局變量作用范圍(可見性)

的關鍵字,該關鍵字告訴編譯器,其聲明的函數和變量可以在本模塊或其它模塊

中使用。

通常,在模塊的頭文件中對本模塊提供給其它模塊引用的函數和全局變量以

關鍵字extern聲明。例如,如果模塊B欲引用該模塊A中定義的全局變量和函

數時只需包含模塊A的頭文件即可。這樣,模塊B中調用模塊A中的函數時,在

編譯階段,模塊B雖然找不到該函數,但是并不會報錯;它會在連接階段中從模

塊A編譯生成的目標代碼中找到此函數

extern"C"是連接申明(linkagedeclaration),被extern"C"修飾的變量

和函數是按照C語言方式編譯和連接的,來看看C++中對類似C的函數是怎樣編

譯的:

作為一種面向對象的語言,C++支持函數重載,而過程式語言C則不支持。

函數被C++編譯后在符號庫中的名字與C語言的不同。例如,假設某個函數的原

型為:

voidfoo(intx,inty);

該函數被C編譯器編譯后在符號庫中的名字為foo,而C++編譯器則會產生

像一foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都采用了

相同的機制,生成的新名字稱為"mangledname")。

_foo_int?int這樣的名字包含了函數名、函數參數數量及類型信息,C++

就是靠這祎機M來實現函數重載的。例如,在C++中,函數voidfoo(intx,

inty)與丫01(1foo(intx,floaty)編譯生成的符號是不相同的,后者為_f

oo_int_floato

同樣地,C++中的變量除支持局部變量外,還支持類成員變量和全局變量。

用戶所編寫程序的類成員變量可能與全局變量同名,我們以'來區分。而本質

上,編譯器在進行編譯時,與函數的處理相似,也為類中的變量取了一個獨一無

二的名字,這個名字與用戶程序中同名的全局變量名字不同。

未加extern"C”聲明時的連接方式

假設在C++中,模塊A的頭文件如下:

//模塊A頭文件moduleA.h

#ifndefMODULE_A_H

#defineMODULE_A_H

intfoo(intx,inty);

#endif

在模塊B中引用該函數:

//模塊B實現文件moduleB.cpp

#include"moduleA.h"

foo(2,3);

實際上,在連接階段,連接器會從模塊A生成的目標文件moduleA.obj中尋

找_foo_int_int這樣的符號!

加extern"C''聲明后的編譯和連接方式

加extern"C”聲明后,模塊A的頭文件變為:

//模塊A頭文件moduleA.h

#ifndefM0DULE_A_H

#defineM0DULE_A_H

extern'C'intfoo(intx,inty);

Wendif

在模塊B的實現文件中仍然調用foo(2,3),其結果是:

(1)模塊A編譯生成fo。的目標代碼時,沒有對其名字進行特殊處理,采用

了C語言的方式;

(2)連接器在為模塊B的目標代碼尋找foo(2,3)調用時,尋找的是未經修改

的符號名一f。。。

如果在模塊A中函數聲明了foo為extern"C"類型,而模塊B中包含的是e

xternintfoo(intx,inty),則模塊B找不到模塊A中的函數;反之亦然。

所以,可以用一句話概括extern"C”這個聲明的真實目的(任何語言中的

任何語法特性的誕生都不是隨意而為的,來源于真實世界的需求驅動。我們在思

考問題時,不能只停留在這個語言是怎么做的,還要問一問它為什么要這么做,

動機是什么,這樣我們可以更深入地理解許多問題):實現C++與C及其它語言

的混合編程。

明白了C++中extern"C”的設立動機,我們下面來具體分析extern通

常的使用技巧:

extern"C”的慣用法

(1)在C++中引用C語言中的函數和變量,在包含C語言頭文件(假設為cEx

ample.h)時,需進行下列處理:

extern"C"

#include"cExample.h"

而在C語言的頭文件中,對其外部函數只能指定為extern類型,C語言中

不支持extern"C"聲明,在.c文件中包含了exten"C〃時會出現編譯語法錯誤。

C++引用C函數例子工程中包含的三個文件的源代碼如下:

/*c語言頭文件:cExample.h*/

#ifndefC_EXAMPLE_H

#defineC_EXAMPLE_H

externintadd(intx,inty);

ttendif

/*c語言實現文件:cExample.c*/

#include"cExample.h"

intadd(intx,inty)

returnx+y;

//C++實現文件,調用add:cppFile.cpp

extern

(

#includez,cExample.h〃

)

intmain(intargc,char*argv[])

add(2,3);

return0;

)

如果C++調用?個C語言編寫的.DLL時,當包括.DLL的頭文件或聲明接口

函數時,應加extern〃C〃{}。

(2)在C中引用C++語言中的函數和變量時,C++的頭文件需添加exteo〃C

:但是在C語言中不能直接引用聲明了extern〃C〃的該頭文件,應該僅將C文

件中將C++中定義的extern〃C〃函數聲明為extern類型。

C引用C++函數例子工程中包含的三個文件的源代碼如下:

〃C++頭文件cppExample.h

#ifndefCPP_EXAMPLE_H

SdefineCPP_EXAMPLE_H

externintadd(intx,inty);

Sendif

〃C++實現文件cppExample.cpp

#include"cppExample.h〃

intadd(intx,inty)

i

returnx+y;

/*C實現文件cFile.c

/*這樣會編譯出錯:#include"cExample.h〃*/

externintadd(intx,inty);

intmain(intargc,char*argv[])

add(2,3);

return0;

}

15題目的解答請參考《C++中extern“C”含義深層探索》注解:

16.關聯、聚合(Aggregation)以及組合(Composition)的區別?

涉及到UML中的一些概念:關聯是表示兩個類的一般性聯系,比如“學生”

和“老師”就是一種關聯關系;聚合表示has-a的關系,是利相對松散的關系,

聚合類不需要對被聚合類負責,如下圖所示,用空的菱形表示聚合關系:

從實現的角度講,聚合可以表示為:

classA{...}classB(A*a;....}

而組合表示contains-a的關系,關聯性強于聚合:組合類與被組合類有相

同的生命周期,組合類要對被組合類負責,采用實心的菱形表示組合關系:

實現的形式是:

classA{...}classB{Aa;...}

參考文章:http://blog.csdn.net/wfwd/archive/2006/05/30/763753.asp

x

http://blog.csdn.net/wfwd/archive/2006/05/30/763760.aspx

17.面向對象的三個基本特征,并簡單敘述之?

1.封裝:將客觀事物抽象成類,每個類對自身的數據和方法實行protecti

on(private,protected,public)

2.繼承:廣義的繼承有三種實現形式:實現繼承(指使用基類的屬性和方法

而無需額外編碼的能力)、可視繼承(子窗體使用父窗體的外觀和實現代碼)、接

口繼承(僅使用屬性和方法,實現滯后到子類實現)。前兩種(類繼承)和后一種(對

象組合=>接口繼承以及純虛函數)構成了功能復用的兩種方式。

3.多態:是將父對象設置成為和個或更多的他的子對象相等的技術,賦

值之后,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。簡

單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。

18.重載(overload)和重寫(overried,有的書也叫做“覆蓋”)的區別?

常考的題目。從定義上來說:

重載:是指允許存在多個同名函數,而這些函數的參數表不同(或許參數個

數不同,或許參數類型不同,或許兩者都不同)。

重寫:是指子類重新定義復類虛函數的方法。

從實現原理上來說:

重載:編譯器根據函數不同的參數表,對同名函數的名稱做修飾,然后這些

同名函數就成了不同的函數(至少對于編譯器來說是這樣的)。如,有兩個同名函

數:functionfunc(p:integer):integer;和functionfunc(p:string):intege

r;0那么編譯器做過修飾后的函數名稱可能是這樣的:int_func、str_func0對

于這兩個函數的調用,在編譯器間就已經確定了,是靜態前。也就是說,它們的

地址在編譯期就綁定了(早綁定),因此,重載和多態無關!

重寫:和多態真正相關。當子類重新定義了父類的虛函數后,父類指針根據

賦給它的不同的子類指針,動態的調用屬于子類的該函數,這樣的函數調用在編

譯期間是無法確定的(調用的子類的虛函數的地址無法給出)。因此,這樣的函數

地址是在運行期綁定的(晚綁定)。

19.多態的作用?

主要是兩個:1.隱藏實現細節,使得代碼能夠模塊化;擴展代碼模塊,實現

代碼重用⑵接口重用:為了類在繼承和派生的時候,保證使用家族中任一類的

實例的某一屬性時的正確調用。

20.Ado與Ado.net的相同與不同?

除了“能夠讓應用程序處理存儲于DBMS中的數據“這一基本相似點外,兩

者沒有太多共同之處。但是Ado使用OLEDB接口并基于微軟的COM技術,而A

DO.NET擁有自己的ADO.NET接口并且基于微軟的.NET體系架構。眾所周知.NE

T體系不同于COM體系,ADO.NET接口也就完全不同于ADO和OLEDB接口,這

也就是說ADO.NET和ADO是兩種數據訪問方式。ADO.net提供對XML的支持。

(二)

1.是不是一個父類寫了一個virtual函數,如果子類覆蓋它的函數不加vi

rtual,也能實現多態?

virtual修飾符會被隱形繼承的。private也被集成,只事派生類沒有訪問

權限而已。virtual可加可不加。子類的空間里有父類的所有變量(static除外)。

同一個函數只存在一個實體(inline除外)。子類覆蓋它的函數不加virtual,

也能實現多態。在子類的空間里,有父類的私有變量。私有變量不能直接訪問。

2.輸入一個字符串,將其逆序后輸出。(使用C++,不建議用偽碼)

Sinclude

usingnamespacestd;

voidmain()

chara[50];memset(a,0,sizeof(a));

inti=0,j;

chart;

cin.getline(a,50,>"n');

for(i=0,j=strlen(a)-1;i

{

t=a[i];

a[i]=a[j];

a[j]=t;

)

cout<

)

//第二種

stringstr;

cin?str;

str.replace;

cout<

3.請簡單描述Windows內存管理的方法。

內存管理是操作系統中的重要部分,兩三句話恐怕誰也說不清楚吧??

我先說個大概,希望能夠拋磚引玉吧

當程序運行時需要從內存中讀出這段程序的代碼。代碼的位置必須在物理內

存中才能被運行,由于現在的操作系統中有非常多的程序運行著,內存中不能夠

完全放下,所以引出了虛擬內存的概念。把哪些不常用的程序片斷就放入虛擬內

存,當需要用到它的時候在load入主存(物理內存)中。這個就是內存管理所要

做的事。內存管理還有另外一件事需要做:計算程序片段在主存中的物理位置,

以便CPU調度。

內存管理有塊式管理,頁式管理,段式和段頁式管理。現在常用段頁式管理

塊式管理:把主存分為一大塊、大塊的,當所需的程序片斷不在主存時就

分配一塊主存空間,把程序片斷load入主存,就算所需的程序片度只有幾個字

節也只能把這一塊分配給它。這樣會造成很大的浪費,平均浪費了50%的內存空

間,但時易于管理。

頁式管理:把主存分為一頁一頁的,每一頁的空間要比一塊一塊的空間小很

多,顯然這種方法的空間利用率要比塊式管理高很多。

段式管理:把主存分為一段段的,每一段的空間又要比一頁一頁的空間小

很多,這種方法在空間利用率上又比頁式管理高很多,但是也有另外一個缺點。

?個程序片斷可能會被分為兒十段,這樣很多時間就會被浪費在計算每一段的物

理地址上(計算機最耗時間的大家都知道是I/O吧)o

段頁式管理:結合了段式管理和頁式管理的優點。把主存分為若干頁,每一

頁又分為若干段。好處就很明顯,不用我多說了吧。

各種內存管理都有它自己的方法來計算出程序片斷在主存中的物理地址,其

實都很相似。

這只是一個大概而已,不足以說明內存管理的皮毛。無論哪一本操作系統書

上都有詳細的講解

4.

#include"stdafx.h"

#defineSQR(X)X*X

intmain(intargc,char*argv[1)

(

inta=10;

intk=2;

intm=1;

a/=SQR(k+m)/SQR(k+m);

printf("%d"n",a);

return0;

)

這道題目的結果是什么啊?

define只是定義而已,在編擇時只是簡單代換X*X而已,并不經過算術法

則的

a/=(k+m)*(k+m)/(k+m)*(k+m);

=>a/=(k+m)*l*(k+m);

=>a=a/9;

=>a=1;

5.

const符號常量;

(1)constchar*p

(2)charconst*p

(3)char*constp

說明上面三種描述的區別;

如果const位于星號的左側,則const就是用來修飾指針所指向的變量,即

指針指向為常量;

如果const位于星號的右側,const就是修飾指針本身,即指針本身是常量。

(1)constchar*p

一個指向char類型的const對象指針,p不是常量,我們可以修改p的值,

使其指向不同的char,但是不能改變它指向非char對象,如:

constchar*p;

charcl=,a;

charc2-b';

p=&cl;//ok

p=&c2;//ok

*p=cl;//error

(2)charconst*p

(3)char*constp

這兩個好象是一樣的,此時*p可以修改,而p不能修改。

(4)constchar*constp

這種是地址及指向對象都不能修改。

6.下面是C語言中兩種if語句判斷方式。請問哪種寫法更好?為什么?

intn;

if(n==10)//第一種判斷方式

if(10==n)//第二種判斷方式

如果少了個=號,編譯時就會報錯,減少了出錯的可能行,可以檢測出是否少

了=

7.下面的代碼有什么問題?

voidDoSomeThing(...)

(

char*p;

p=malloc(1024);//分配IK的空間

if(NULL==p)

return;

p=realloc(p,2048);//空間不夠,重新分配到2K

if(NULL==p)

return;

)

A:

p=malloc(1024);應該寫成:p=(char*)malloc(1024);

沒有釋放P的空間,造成內存泄漏。

8.下面的代碼有什么問題?并請給出正確的寫法。

voidDoSomeThing(char*p)

(

charstr[16];

intn;

assert(NULL!=p);

sscanf(p,/z%s%dz,,str,n);

if(0==strcmp(str,"something"))

A:

sscanf(p,str,n);這句該寫成:sscanf(p,〃%s%d〃,str,&

n);

9.下面代碼有什么錯誤?

Voidtestl()

i

charstring[10];

char*strl=〃0123456789〃;

strcpy(string,strl);

)

數組越界

10.下面代碼有什么問題?

Voidtest20

(

charstring[10],strl[10];

for(i=0;i<10;i++)

(

strl[i]='a';

strcpy(string,strl);

數組越界

11.下面代碼有什么問題?

Voidtest3(char*strl)

{

charstring[10];

if(strlen(strl)<=10)

J

strcpy(string,strl);

)

)

==數組越界

==strcpy拷貝的結束標志是查找字符串中的“0因此如果字符串中沒有遇

到“0的話會一直復制,直到遇到“0,上面的123都因此產生越界的情況

建議使用strncpy和memcpy

12.下面代碼有什么問題?

#defineMAX_SRM256

DSNget_SRM_no()

(

staticintSRM_no;〃是不是這里沒賦初值?

intI;

for(1=0;I

{

SRM_no%=MAX_SRM;

if(MY_SRM.state==IDLE)

break;

if(I>=MAXSRM)

return(NULL_SRM);

else

returnSRM_no;

)

系統會初始化staticint變量為0,但該值會一直保存,所謂的不可重入??.

13.寫出運行結果:

{//testl

charstr[]="world”;cout?sizeof(str)<<〃:〃;

char*p=str;cout<<sizeof(p)?〃:〃;

chari=10;cout<<sizeof(i)?”:〃;

void*pp=malloc(10);cout<<sizeof(p)?endl;

)

6:4:1:4

14.寫出運行結果:

{//test2

unionV{

structX{

unsignedcharsi:2;

unsignedchars2:3;

unsignedchars3:3;

}x;

unsignedcharc;

}v;

v.c=100;

printfv.x.s3);

3

15.用C++寫個程序,如何判斷一個操作系統是16位還是32位的?不能用s

izeof()函數

A1:

16位的系統下,

inti=65536;

cout?i;//輸出0;

inti=65535;

cout?i;//輸出T;

32位的系統下,

inti=65536;

cout?i;//輸出65536;

inti=65535;

cout?i;//輸出65535;

A2:

inta=~0;

if(a>65536)

{

cout<</z32bil”<

)

else

I

cout?,/16bit/z<

16.C和C++有什么不同?

從機制上:C是面向過程的(但C也可以編寫面向對象的程序);C++是面向對

象的,提供了類。但是,

C++編寫面向對象的程序比C容易

從適用的方向:C適合要求代碼體積小的,效率高的場合,如嵌入式;C++適

合更上層的,復雜的;Uinux核心大部分是c寫的,因為它是系統軟件,效率

要求極高。

從名稱上也可以看出,C++比c多了+,說明C++是c的超集;那為什么不叫c

+而叫C++呢,是因為C++比

C來說擴充的東西太多了,所以就在C后面放上兩個+;于是就成了C++

C語言是結構化編程語言,C++是面向對象編程語言。

C++側重于對象而不是過程,側重于類的設計而不是邏輯的設計。

17.在不用第三方參數的情況下,交換兩個參數的值

Sinclude

voidmain()

{

inti=60;

intj=50;

i=i+j;

j=i-j;

i=i-j;

printf(,,i=%dV,,i);

printf("j=%d"n",j);

}

方法二:

1=j;

J=1;

1=j;

方法三:

//用加減實現,而且不會溢出

a=a+b-(b=a)

18.有關位域的面試題(為什么輸出的是一個奇怪的字符)

a.t='b';效果相當于a.t='b'&Oxf;

,b'—>01100010

,b'&Oxf—>>00000010

所以輸出Ascii碼為2的特殊字符

chart:4;就是4bit的字符變量,同樣

unsignedshorti:8;就是8bit的無符號短整形變量

19.inti=10,j=10,k=3;k*=i+j;k最后的值是?

60

20.進程間通信的方式有?

進程間通信的方式有共享內存,管道,Socket,消息隊列,DDE等

21.

structA

(

chart:4;

chark:4;

unsignedshorti:8;

unsignedlongm;

sizeof(A)=?(不考慮邊界對齊)

7

structCELL//DeclareCELLbitfield

unsignedcharacter:8;//00000000????????

unsignedforeground:3;//00000???00000000

unsignedintensity:1;//0000700000000000

unsignedbackground:3;//0???000000000000

unsignedblink:1;//2000000000000000

}screen[25][80];//Arrayofbitfields

二、位結構

位結構是一種特殊的結構,在需按位訪問一個字節或字的多個位時,位結

比按位運算符更加方便。

位結構定義的一般形式為:

struct位結構名{

數據類型變量名:整型常數;

數據類型變量名:整型常數;

}位結構變量;

其中:數據類型必須是int(unsigned或signed)。整型常數必須是非負的

數,范圍是0~15,表示二進制位的個數,即表示有多少位。

變量名是選擇項,可以不命名,這樣規定是為了排列需要。

例如:下面定義了一個位結構。

struct{

unsignedincon:8;/*incon占用低字節的0~7共8位*/

unsignedtxcolor:4;/*txcolor占用高字節的0~3位共4位*/

unsignedbgcolor:3;/*bgcolor占用高字節的4~6位共3位*/

unsignedblink:1;/*blink占用高字節的第7位*/

}ch;

位結構成員的訪問與結構成員的訪問相同。

例如:訪問上例位結構中的bgcolor成員可寫成:

ch.bgcolor

注意:

1.位結構中的成員可以定義為unsigned,也可定義為signed,但當成員

度為1時,會被認為是unsigned類型。因為單個位不可能具有符號。

2.位結構中的成員不能使用數組和指針,但位結構變量可以是數組和指

針,

如果是指針,其成員訪問方式同結構指針。

3.位結構總長度(位數),是各個位成員定義的位數之和,可以超過兩個字

節。

4.位結構成員可以與其它結構成員一起使用。

例如:

structinfo{

charname[8];

intage;

structaddraddress;

floatpay;

unsignedstate:1;

unsignedpay:1;

}workers;

上例的結構定義了關于一個工人的信息。其中有兩個位結構成員,每個位結

構成員只有一位,因此只占一個字節但保存了兩個信息,該字節中第一位

表示工

人的狀態,第二位表示工資是否已發放。由此可見使用位結構可以節省存貯

空間。

22.下面的函數實現在一個固定的數上加上一個數,有什么錯誤,改正

intadd_n(intn)

(

staticinti=100;

i+=n;

return1;

答:

因為static使得i的值會保留上次的值。

去掉static就可了

23.下面的代碼有什么問題?

classA

{

public:

A(){p=this;}

~A(){if(p!=NULL){deletep;p=NULL;}}

A*p;

);

答:

會引起無限遞歸

24.

uniona{

inta_intl;

doublea_double;

inta_int2;

);

typedefstruct

{

aal;

chary;

}b;

classc

doublecdouble;

bbl;

aa2;

);

輸出cout<

答:

VC6環境下得出的結果是32

另:

我(sun)在VC6.0+win2k下做過試驗:

short-2

int-4

float-4

double-8

指針-4

sizeof(union),以結構里面size最大的為union的size

25.i最后等于多少?

inti=1;

intj=i++;

if((i>j++)&&(i++==j))i+=j;

答:

i=5

26.

unsignedshortarray[]={1,2,3,4,5,6,7};

inti=3;

*(array+i)=?

答:

4

27.

classA

(

virtualvoidfund0;

voidfunc2();

)

ClassB:classA

(

voidfund(){cout<<〃funlinclassB〃?endl;}

virtualvoidfunc2(){cout<<,zfun2inclassB〃?endl;}

)

A,A中的funcl和B中的func2都是虛函數.

B,A中的funcl和B中的func2都不是虛函數.

C,A中的func2是虛函數.,B中的funcl不是虛函數.

D,A中的func2不是虛函數,B中的funcl是虛函數.

答:

A

28.

數據庫:抽出部門,平均工資,要求按部門的字符串順序排序,不能含有〃

humanresource”部門,

employee結構如下:employee_id,employee_name,departid,departna

me,wage

紋口??

selectdepart_name,avg(wage)

fromemployee

wheredepart_name<>'humanresource,

groupbydepart_name

orderbydepart_name

29.

給定如下SQL數據庫:Test(numINT(4))請用一條SQL語句返回num的最

小值,但不許使用統計功能,如MIN,MAX等

林口.?

selecttop1num

fromTest

orderbynumdesc

30.

輸出下面程序結果。

Sinclude

classA

{

public:

virtualvoidprint(void)

(

cout<<"A::print()“<

)

);

classB:publicA

{

public:

virtualvoidprint(void)

{

cout<<z/B::print()z,<

);

);

classC:publicB

public:

virtualvoidprint(void)

cout?z,C::print()〃<

}

};

voidprint(Aa)

I

a.print();

)

voidmain(void)

I

Aa,*pa,*pb,*pc;

Bb;

Cc;

pa=&a;

pb=&b;

pc=&c;

a.print();

b.print();

c.print();

pa->print();

pb->print();

pc->print();

print(a);

print(b);

print(c);

A:

A::print()

B::print()

C::print()

A::print()

B::print()

C::print()

A::print()

A::print()

A::print()

31.

試編寫函數判斷計算機的字節存儲順序是開序(littleendian)還是降序(b

igendian)

答:

boolIsBigendian()

(

unsignedshortusData=0x1122;

unsignedchar*pucData=(unsignedchar*)&usData;

return(*pucData==0x22);

32.簡述CriticalSection和Mutex的不同點

答:

對幾種同步對象的總結

1.CriticalSection

A.速度快

B.不能用于不同進程

C.不能進行資源統計(每次只可以有一個線程對共享資源進行存取)

2.Mutex

A.速度慢

B.可用于不同進程

C.不能進行資源統計

3.Semaphore

A.速度慢

B.可用于不同進程

C.可進行資源統計(可以讓一個或超過一個線程對共享資源進行存取)

4.Event

A.速度慢

B.可用于不同進程

C.可進行資源統計

33.?個數據庫中有兩個表:

?張表

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論