判斷題(對的寫T,錯的寫F并說明原因,每小題4分,共20分)
1、有數組定義int a[2][2]={,{2,3}};則a[0][1]的值為0。()
答案:T、如果寫確的話,應該是0,0,2,3。
2、int (*ptr) (),則ptr是一維數組的名字。()
答案: F、函數指針,指向函數的指針,是一個指針。查看函數指針和指針函數區別
3、指針在任何情況下都可進行,,=,=,==運算。()
答案: T、指針,實際是地址0×3423..,可以進行運算。
4、switch(c) 語句中c可以是int ,long,char ,float ,unsigned int 類型。()
答案:F,字型,或者整形,float在計算機中本來就不確定,比如10.9999?
5、#define print(x) printf("the no, "#x",is ")
答案:T,解釋如下:在#define中,標準只定義了#和##兩種操作。#用來把參數轉換成字串,##則用來連接兩個前后兩個參數,把它們變成一個字串。
#include stdio.h
#define paster( n ) printf( “token ” #n” = %dn “, token##n )
int main()
{
int token9=10;
paster(9);
return 0;
}
運行結果:token 9 = 10
填空題(共30分)
1、在windows下,寫出運行結果,每空2分,共10分。
char str[ ]= "Hello";
char *p=str;
int n=10;
sizeof(str)=( )
sizeof(p)=( )
sizeof(n)=( )
void func(char str[100])
{ }
sizeof(str)=( )
答案:6、4、4、4(數組做參數退化成指針,點我查看)
2、void setmemory(char **p, int num) 10分
{ *p=(char *) malloc(num);}
void test(void)
{ char *str=NULL;
setmemory(str,100);
strcpy(str,"hello");
printf(str);
}
運行test函數有什麼結果?()
答案:hello
3、設int arr[]={6,7,8,9,10}; 10分
int *ptr=arr;
*(ptr++)+=123;
printf("%d,%d",*ptr,*(++ptr));
答案:8,8. 在vc6.0下是從有到左,這里先*(++ptr) 后*pt,于是結果為8,8。
問答題(每題5分,共30分)
1 . 用預處理指令#define 聲明一個常數,用以表明1年中有多少秒(忽略閏年問題)
答案: #define SECONDS (60*60*24*365)L //無分號、長整型
2 . 寫一個”標準”宏MIN ,這個宏輸入兩個參數并返回較小的一個。
答案:#defined MIN(a,b) ((a b) ? (a) : (b))
3. 預處理器標識#error的目的是什麼?
答案:停止編譯,提示錯誤
4. 嵌入式系統中經常要用到無限循環,你怎麼樣用C編寫死循環呢?
答案:for()、while(1)、LOOP: goto LOOP;
5.關鍵字const有什麼含意?
答案:常量,該數值不可改變。并可做修飾,比如常量指針 int const *p;
編程題(每題10分,共20分)
1、不使用庫函數,編寫函數int strcmp(char *source, char *dest)
相等返回0,不等返回-1;
答案:字串比較函數,可以用for循環,判斷*source == *dest
2、寫一函數int fun(char *p)判斷一字串是否為回文,是返回1,不是返回0,出錯返回-1
答案:判斷是否相同,條件ij;for前for后或者while(ij),相等繼續,不等return。。。
1、找錯
void test1()
{
char string[10];
char* str1="0123456789"
strcpy(string, str1);
}
這里string數組越界,因為字串長度為10,還有一個結束‘’。所以總共有11個字長度。string數組大小為10,這里越界了。
PS:使用strcpy函數的時候一定要注意前面目的數組的大小一定要大于后面字串的大小,否則便是訪問越界。
void test2()
{
char string[10], str1[10];
for(i=0; i10;i++)
{
str1[i] =’a’;
}
strcpy(string, str1);
}
這里有一個一眼就能看出的問題,那就是變量i沒有定義,這在代碼編譯階段編譯器可以幫你發現,很容易搞定。然而很多問題是自己造成的漏洞,編譯器是幫不上什麼忙的。這里最大的問題還是str1沒有結束,因為strcpy的第二個參數應該是一個字串常量。該函數就是利用判斷第二個參數的結束來得到是否拷貝完畢。所以在for循環后面應加上str1p[9] = ‘’;
PS:字數組和字串的最明顯的區別就是字串會被默認的加上結束‘’。
void test3(char* str1)
{
char string[10];
if(strlen(str1)=10)
{
strcpy(string, str1);
}
}
這里的問題仍是越界問題。strlen函數得到字串除結束外的長度。如果這里是=10話,就很明顯越界了。
小結:上面的三個找錯的函數,主要是考查對字串和字數組的概念的掌握以及對strcpy函數和strlen函數的理解。
2、找錯
DSN get_SRM_no()
{
static int SRM_no;
int I;
for(I=0;IMAX_SRM;I++)
{
SRM_no %= MAX_SRM;
if(MY_SRM.state==IDLE)
{
break;
}
}
if(I=MAX_SRM)
return (NULL_SRM);
else
return SRM_no;
}
這里for循環的判斷語句是后來我加上的,估計在
上流傳的時候被人給弄丟了,根據對程序的分析,給補上了。估計錯誤應該不是這兒。
簡單的閱讀一下這個函數,可以大概的可以猜測出這個函數的功能是分配一個空閑的SRAM塊。方法:從上次分配的RAM塊后的RAM塊開始檢測SRAM每個RAM塊,看是否是IDLE狀態,如果是IDLE則返回當前的RAM塊的號SRM_no.如果所有的RAM塊都不是IDLE狀態,則意味著無法分配一個RAM給函數調用者,返回一個表示沒有RAM可分配的標志(NULL_SRM)。
經過上面的分析,則這里可以知道,這個函數的錯誤是for循環里面沒有給SRM_no這個變量累加1.
3、寫出程序運行結果
int sum(int a)
{
auto int c=0;
static int b=3;
c+=1;
b+=2;
return(a+b+c);
}
void main()
{
int I;
int a=2;
for(I=0;I5;I++)
{
printf("%d,", sum(a));
}
}
運行結果是:8,10,12,14,16,
在求和函數sum里面c是auto變量,根據auto變量特性知每次調用sum函數時變量c都會自動賦值為0.b是static變量,根據static變量特性知每次調用sum函數時變量b都會使用上次調用sum函數時b保存的值。
簡單的分析一下函數,可以知道,若傳入的參數不變,則每次調用sum函數返回的結果,都比上次多2.所以答案是:8,10,12,14,16,
4、func(1) = ?
int func(int a)
{
int b;
switch(a)
{
case 1: 30;
case 2: 20;
case 3: 16;
default: 0;
}
return b;
}
在 case 語句中可能忘記了對變量b賦值。如果改為下面的代碼:
int func(int a)
{
int b;
switch(a)
{
case 1: b = 30;
case 2: b = 20;
case 3: b = 16;
default: b = 0;
}
return b;
}
因為case語句中漏掉了break語句,所以無論傳給函數的參數是多少,運行結果均為0.
1、局部變量能否和全局變量重名?
答:能,局部會全局。要用全局變量,需要使用"::" ;局部變量可以與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。對于有些編譯器而言,在同一個函數內可以定義多個同 名的局部變量,比如在兩個循環體內都定義一個同名的局部變量,而那個局部變量的作用域就在那個循環體內。
2、如何引用一個已經定義過的全局變量?
答:extern 可以用引用頭文件的方式,也可以用extern關鍵字,如果用引用頭文件方式來引用某個在頭文件中聲明的全局變理,假定你將那個編寫錯了,那麼在編譯期 間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那麼在編譯期間不會報錯,而在連接期間報錯。
3、全局變量可不可以定義在可被多個.C文件
的頭文件中?為什麼?
答:可以,在不同的C文件中以static形式來聲明同名全局變量。 可以在不同的C文件中聲明同名的全局變量,前提是其中只能有一個C文件中對此變量賦初值,此時連接不會出錯.
4、請寫出下列代碼的輸出內容
#include stdio.h
int main(void)
{
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
5、static全局變量與普通的全局變量有什麼區別?static局部變量和普通局部變量有什麼區別?static函數與普通函數有什麼區別?
答: 1) 全局變量(外部變量)的說明之前再冠以static 就構成了靜態的全局變量。全局變量本身就是靜態存儲方式, 靜態全局變量當然也是靜態存儲方式。 這兩者在存儲方式上并無不同。這兩者的區別在于非靜態全局變量的作用域是整個源程序, 當一個源程序由多個源文件組成時,非靜態的全局變量在各個源文件中都是有效的。 而靜態全局變量則限制了其作用域, 即只在定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。由于靜態全局變量的作用域局限于一個源文件內,只能為該源文件內的函數公用, 因此可以避免在其它源文件中引起錯誤。
2) 從以上分析可以看出, 把局部變量改變為靜態變量后是改變了它的存儲方式即改變了它的生存期。把全局變量改變為靜態變量后是改變了它的作用域,限制了它的使用范圍。 3) static函數與普通函數作用域不同,僅在本文件。只在當前源文件中使用的函數應該說明為內部函數(static),內部函數應該在當前源文件中說明和定義。對于可在當前源文件以外使用的函數,應該在一個頭文件中說明,要使用這些函數的源文件要
這個頭文件
綜上所述:
static全局變量與普通的全局變量有什麼區別:
static全局變量只初使化一次,防止在其他文件單元中被引用;
static局部變量和普通局部變量有什麼區別:
static局部變量只被初始化一次,下一次依據上一次結果值;
static函數與普通函數有什麼區別:
static函數在內存中只有一份,普通函數在每個被調用中維持一份拷貝
6、程序的局部變量存在于(堆棧)中,全局變量存在于(靜態區 )中,動態申請數據存在于( 堆)中。
7、設有以下說明和定義:
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 data)+sizeof(max));的執行結果是:___52____
考點:區別struct與union.(一般假定在32位機器上)
答:DATE是一個union, 變量公用空間. 里面最大的變量類型是int[5], 占用20個字節. 所以它的大小是20. data是一個struct, 每個變量分開占用空間. 依次為int4 + DATE20 + double8 = 32. 所以結果是 20 + 32 = 52. 當然…在某些16位編輯器下, int可能是2字節,那麼結果是 int2 + DATE10 + double8 = 20
8、隊列和棧有什麼區別?
隊列先進先出,棧后進先出
9、寫出下列代碼的輸出內容
#include 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)
{
FUNC1 p=inc;
int temp =p(arg1);
fun(temp,arg1, arg2);
printf("%dn",*arg2);
}
main()
{
int a; //局部變量a為0;
show(multi,10,a);
return 0;
}
答:110
10、請找出下面代碼中的所有錯誤 (題目不錯,值得一看)
說明:以下代碼是把一個字串倒序,如“abcd”倒序后變為“dcba”
#include"string.h"
main()
{
char*src=http://www.nbakan8.com/sxxzx/"hello,world"
char* dest=NULL;
int len=strlen(src);
dest=(char*)malloc(len);
char* d=dest;
char* s=src[len];
while(len–!=0)
d++=s–;
printf("%s",dest);
return 0;
}
答:
方法1:一共有4個錯誤;
int main()
{
char* src = http://www.nbakan8.com/sxxzx/"hello,world"
int len = strlen(src);
char* dest = (char*)malloc(len+1);//要為分配一個空間 char* d = dest;
char* s = src[len-1]; //指向最后一個字
while( len– != 0 )
*d++=*s–;
*d = 0; //尾部要加’’
printf("%sn",dest);
free(dest); // 使用完,應當釋放空間,以免造成內存匯泄露
dest = NULL; //防止產生野指針
return 0;
}
方法2: (方法一需要額外的存儲空間,效率不高.) 不錯的想法
#include stdio.h
#include string.h
main()
{
char str[]="hello,world"
int len=strlen(str);
char t;
for(int i=0; ilen/2; i++)
{
t=str[i];
str[i]=str[len-i-1]; //小心一點
str[len-i-1]=t;
}
printf("%s",str);
return 0;
}
11.對于一個頻繁使用的短小函數,在C語言中應用什麼實現,在C++中應用什麼實現?
c用宏定義,c++用inline
12.直接鏈接兩個信令點的一組鏈路稱作什麼?
PPP點到點連接
13.接入
用的是什麼接口?
V5接口
14.voip都用了那些協議?
H.323協議簇、SIP協議、Skype協議、H.248和MGCP協議
15.軟件測試都有那些種類?
黑盒:針對系統功能的測試
白盒:測試函數功能,各函數接口
16.確定模塊的功能和模塊的接口是在軟件設計的那個隊段完成的?
概要設計階段
17.
unsigned char *p1;
unsigned long *p2;
p1=(unsigned char *)0x801000;
p2=(unsigned long *)0x810000;
請問p1+5= ;
p2+5= ;
答案:0x801005(相當于加上5位) 0x810014(相當于加上20位);
選擇題:
21.Ethter
鏈接到Inter
用到以下那個協議? D
A.HDLC;B.ARP;C.UDP;D.TCP;E.ID
22.屬于
絡層協議的是:( B C)
A.TCP;B.IP;C.ICMP;D.X.25
23.Windows消息調度機制是:(C)
A.指令隊列;B.指令堆棧;C.消息隊列;D.消息堆棧;
找錯題:
25.請問下面程序有什麼錯誤?
int a[60][250][1000],i,j,k;
for(k=0;kMax_GT_Length)
{ return GT_Length_ERROR;
} ……. }
答: 死循環//
問答題:
29.IP Phone的原理是什麼?
IP(又稱IP PHONE或VoIP)是建立在IP技術上的分組化、數字化傳輸技術,其基本原理是:通過壓縮算法對數據進行壓縮編碼處理,然后把這些數據按 IP等相關協議進行打包,經過IP
絡把數據包傳輸到接收地,再把這些數據包串起來,經過解壓處理后,恢復成原來的信號,從而達到由IP
絡 傳送的目的。
30.TCP/IP通信建立的過程怎樣,端口有什麼作用?
三次握手,確定是哪個應用程序使用該協議
31.1號信令和7號信令有什麼區別,我國某前廣泛使用的是那一種?
1號信令接續慢,但是穩定,可靠。
7號信令的特點是:信令速度快,具有提供大量信令的潛力,具有改變和增加信令的靈活性,便于新業務,在通話時可以隨意處理信令,成本低。目前得到廣泛應用。
32.列舉5種以上的新業務
如“鬧鐘服務”、“免干擾服務”、“服務”、“轉移呼叫”、“遇忙回叫”、“缺席用戶服務”、“追查惡意呼叫”、“三方通話”、“會議”、“呼出限制”、“來電顯示”、“虛擬
”等
四.找錯題:
1.請問下面程序有什麼錯誤?
int a[60][250][1000],i,j,k;
for(k=0;k=1000;k++)
for(j=0;j250;j++)
for(i=0;i60;i++)
a[i][j][k]=0;
答: 把循環語句內外換一下
2.#define Max_CB 500
void LmiQueryCSmd(Struct MSgCB * pmsg)
{
unsigned char ucCmdNum;
……
for(ucCmdNum=0;ucCmdNumMax_CB;ucCmdNum++)
{
……;
}
答: 死循環,unsigned int的取值范圍是0~255
3.以下是求一個數的的程序,請找出錯誤:
#define SQUARE(a)((a)*(a))
int a=5;
int b;
b=SQUARE(a++);
答:結果與編譯器相關,得到的可能不是值.
微軟亞洲技術中心的面試題!!!
1.進程和線程的差別。
答:線程是指進程內的一個執行單元,也是進程內的可調度實體.
與進程的區別:
(1)調度:線程作為調度和分配的基本單位,進程作為擁有的基本單位
(2)并發性:不僅進程之間可以并發執行,同一個進程的多個線程之間也可并發執行
(3)擁有:進程是擁有的一個獨立單位,線程不擁有系統,但可以訪問隸屬于進程的.
(4)系統開銷:在創建或撤消進程時,由于系統都要為之分配和回收,導致系統的開銷明顯大于創建或撤消線程時的開銷。
2.測試方法
答:人工測試:個人復查、抽查和會審
機器測試:黑盒測試和白盒測試
3.Heap與stack的差別。
答:Heap是堆,stack是棧。
Stack的空間由操作系統自動分配/釋放,Heap上的空間手動分配/釋放。
Stack空間有限,Heap是很大的自由存儲區
C中的malloc函數分配的內存空間即在堆上,C++中對應的是new操作。
程序在編譯期對變量和函數分配內存都在棧上進行,且程序運行過程中函數調用時參數的傳遞也在棧上進行
4.Windows下的內存是如何管理的?
分頁管理
8.談談IA32下的分頁機制
小頁(4K)兩級分頁,大頁(4M)一級
9.給兩個變量,如何找出一個帶環單鏈表中是什麼地方出現環的?
一個遞增一,一個遞增二,他們指向同一個接點時就是環出現的地方
10.在IA32中一共有多少種辦法從用戶態跳到內核態?
通過調用門,從ring3到ring0,中斷從ring3到ring0,進入vm86等等
11.如果只想讓程序有一個實例運行,不能運行兩個。像winamp一樣,只能開一個窗口,怎樣實現?
用內存映射或全局原子(互斥變量)、查找窗口句柄..
FindWindow,互斥,寫標志到文件或注冊表,共享內存。.
12.如何截取鍵盤的響應,讓所有的'a’變成'b’?
答:鍵盤鉤子SetWindowsHookEx
14.存儲過程是什麼?有什麼用?有什麼優點?
答:我的理解就是一堆sql的,可以建立非常復雜的查詢,編譯運行,所以運行一次后,以后再運行速度比單獨執行SQL快很多
15.Template有什麼特點?什麼時候用?
答: Template可以獨立于任何特定的類型編寫代碼,是泛型編程的基礎.
編寫的類和函數能夠多態的用于跨越編譯時不相關的類型時,用Template.
模板主要用于STL中的容器,算法,迭代器等以及模板元編程.
(C++的template是實現在庫設計和嵌入式設計中的關鍵。
template能實現抽象和效率的結合;同時template還能有效地防止代碼膨脹)
16.談談Windows DNA結構的特點和優點。
答:Windows Distributed interNet Application Architecture(Windows分布式應用結構,簡稱Windows DNA)是微軟創建新一代高適應性商業解決方案的框架,它使公司能夠充分地挖掘數字神經系統的優點。Windows DNA是第一個將Inter
、客戶/、和用于計算的PC模型結合并集成在一起的為新一類分布式計算方案而設計的應用軟件體系結構
17.
絡編程中設計并發,使用多進程與多線程,請問有什麼區別?
答: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)
答:int do_dup(int a[],int N) //未經調試
{
int sun = 0;
int sum2;
for(int i=0;iN;++i)
{
Sum+=a[i];
}
Sum2 = (1+N-1)*N/2;
Return (sum-sum2);
}
3 一語句實現x是否為2的若干次冪的判斷
答:方法1)int i = 512;
cout boolalpha ((i (i – 1)) ? false : true) endl; //位與為0,則表示是2的若干次冪
2)return (xN==1);
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) //假定p=4,n=3
{
unsigned int _t = 0;
unsigned int _a = 1;
for(int i = 0; i n; ++i)//循環的目的主要是-t
{
_t |= _a; //位或
_a = _a 1;
}
_t = _t p; //轉換后_t變為1110000
x ^= _t; /異或,將原來的位取反
return x;
}
慧通:
1. 什麼是預編譯,何時需要預編譯:
答: 就是指程序執行前的一些預處理工作,主要指#表示的.
何時需要預編譯?
1)、總是使用不經常改動的大型代碼體。
2)、程序由多個模塊組成,所有模塊都使用一組標準的
文件和相同的編譯選項。在這種情況下,可以將所有
文件預編譯為一個預編譯頭。
2. 下述三個有什麼區別?
char * const p;
char const * p
const char *p
解答:
char * const p; //常量指針,p的值不可以修改
char const * p;//指向常量的指針,指向的常量值不可以改
const char *p; //和char const *p
3. 解釋下列輸出結果
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是指針,它們指向相同的常量區域。
4. 以下代碼中的兩個sizeof用法有問題嗎?[C易]
void UpperCase( char str[] ) // 將 str 中的小寫字母轉換成大寫字母
{
for( size_t i=0; isizeof(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。
注意:數組名作為函數參數時,退化為指針.
數組名作為sizeof()參數時,數組名不退化,因為sizeof不是函數.
4. 一個32位的機器,該機器的指針是多少位
指針是多少位只要看地址總線的位數就行了。80386以后的機子都是32的數據總線。所以指針的位數就是4個字節了。
5. 指出下面代碼的輸出,并解釋為什麼。(不錯,對地址掌握的深入挖潛)
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].
6.請問以下代碼有什麼問題:
1).
int main()
{
char a;
char *str=a;
strcpy(str,"hello");
printf(str);
return 0;
}
答;沒有為str分配內存空間,將會發生異常
問題出在將一個字串復制進一個字變量指針所指地址。雖然可以正確輸出結果,但因為越界進行內在讀寫而導致程序崩潰。
Strcpy的在庫函數string.h中.程序的主要錯誤在于越界進行內存讀寫導致程序崩潰//
2).
char* s="AAA"
printf("%s",s);
s[0]='B'
printf("%s",s);
有什麼錯?
答: "AAA"是字串常量。s是指針,指向這個字串常量,所以聲明s的時候就有問題。
cosnt char* s="AAA"
然后又因為是常量,所以對是s[0]的賦值操作是不合法的。
1、寫一個“標準”宏,這個宏輸入兩個參數并返回較小的一個。
答:#define Min(X, Y) ((X)(Y)?(Y):(X)) //結尾沒有;
2、嵌入式系統中經常要用到無限循環,你怎麼用C編寫死循環。
答:while(1){}或者for() //前面那個較好
3、關鍵字static的作用是什麼?
答:1)定義靜態局部變量,作用域從函數開始到結束.
2) 在模塊內的static函數只可被這一模塊內的其它函數調用,這個函數的使用范圍被限制在聲明它的模塊內;
3) 在類中的static成員變量屬于整個類所擁有,對類的所有對象只有一份拷貝
4、關鍵字const有什麼含意?
答 :1)表示常量不可以修改的變量。
2)可以修飾參數,作為輸入參數.
3)修飾函數,防止以外的改動.
4)修飾類的成員函數,不改變類中的數據成員.
5、關鍵字volatile有什麼含意?并舉出三個不同的例子?
答: 提示編譯器對象的值可能在編譯器未監測到的情況下改變。
例子: 硬件時鐘;多線程中被多個任務共享的變量等
6. int (*s[10])(int) 表示的是什麼啊
int (*s[10])(int) 函數指針數組,每個指針指向一個int func(int param)的函數。
1.有以下表達式:
int a=248; b=4;int const c=21;const int *d=a;
int *const e=b;int const *f const =a;
請問下列表達式哪些會被編譯器禁止?為什麼?
答:*c=32;d=b;*d=43;e=34;e=a;f=0x321f;
*c 這是個什麼東東,禁止
*d 說了是const, 禁止
e = a 說了是const 禁止
const *f const =a; 禁止
2.兩個變量的值,不使用第三個變量。即a=3,b=5,之后a=5,b=3;
答:有兩種解法, 一種用算術算法, 一種用^(異或)
a = a + b;
b = a – b;
a = a – b;
or
a = a^b;// 只能對int,char..
b = a^b;
a = a^b;
or
a ^= b ^= a;
3.c和c++中的struct有什麼不同?
答: c和c++中struct的主要區別是c中的struct不可以含有成員函數,而c++中的struct可以。c++中struct和class的主要區別在于默認的存取權限不同,struct默認為public,而class默認為private.
4.#include stdio.h
#include stdlib.h
void getmemory(char *p)
{
p=(char *) malloc(100);
}
int main( )
{
char *str=NULL;
getmemory(str);
strcpy(p,"hello world");
printf("%s/n",str);
free(str);
return 0;
}
答: 程序崩潰,getmemory中的malloc 不能返回動態內存, free()對str操作很危險
5.char szstr[10];
strcpy(szstr,"0123456789");
產生什麼結果?為什麼?
答;正常輸出,長度不一樣,會造成的OS,覆蓋別的內容.
6.列舉幾種進程的同步機制,并比較其優缺點。
答:原子操作
信號量機制
自旋鎖
管程,會合,分布式系統
7.進程之間通信的途徑
答 共享存儲系統
消息傳遞系統
管道:以文件系統為基礎
面試經典試題
silver6 | 02 一月, 2007 11:41
面試經典試題
Author:Vince
————即使你是個編程高手,你在面試前也應該要看看這套題,她也許會給你帶來好運,否則你有可能后悔當初為什麼沒有看而跳樓,這樣我會很內疚的。這套題看似簡單,但你未必能得高分,即使你看不懂也要把她背下來!
歡迎轉載此文,轉載時請注明
:文斯測試技術研究中心 [url]http://blog.csdn.
/vincetest[/url]
1 編程基礎
1.1 基本概念
1. const的理解:const char*, char const*, char*const的區別問題幾乎是C++面試中每次 都會有的題目。 事實上這個概念誰都有只是三種聲明方式非常相似很容易記混。 Bjarne在他的The C++ Programming Language里面給出過一個助記的方法: 把一個聲明從右向左讀。
char * const cp; ( * 讀成 pointer to )
cp is a const pointer to char
const char * p;
p is a pointer to const char;
char const * p;
同上因為C++里面沒有const*的運算,所以const只能屬于前面的類型。
2. c指針
int *p[n];—–指針數組,每個元素均為指向整型數據的指針。
int (*p)[n];——p為指向一維數組的指針,這個一維數組有n個整型數據。
int *p();———-函數帶回指針,指針指向返回的值。
int (*p)();——p為指向函數的指針。
3. 數組越界問題 (這個題目還是有點小險的)
下面這個程序執行后會有什麼錯誤或者效果:
#define MAX 255
int main()
{
unsigned char A[MAX],i;
for (i=0;i=MAX;i++)
A[i]=i;
}
解答:MAX=255,數組A的下標范圍為:0..MAX-1,這是其一,其二 當i循環到255時,循環內執行: A[255]=255;這句本身沒有問題,但是返回for (i=0;i=MAX;i++)語句時,由于unsigned char的取值范圍在(0..255),i++以后i又為0了..無限循環下去.
注:char類型為一個字節,取值范圍是[-128,127],unsigned char [0 ,255]
4. C++:memset ,memcpy 和strcpy 的根本區別?
答:#include "memory.h"
memset用來對一段內存空間全部設置為某個字,一般用在對定義的字串進行初始化為' '或'';例:char a[100];memset(a, '', sizeof(a));
memcpy用來做內存拷貝,你可以拿它拷貝任何數據類型的對象,可以指定拷貝的數據長度;例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),會造成b的內存地址溢出。
strcpy就只能拷貝字串了,它遇到''就結束拷貝;例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字串長度(第一個''之前)是否超過50位,如超過,則會造成b的內存地址溢出。
strcpy
原型:extern char *strcpy(char *dest,char *src);
{
ASSERT((dest!=NULL)(src!=NULL));
Char *address = dest;
While((*dest++=*src++)!=’’)
Continue;
Return dest;
}
用法:#include string.h
功能:把src所指由NULL結束的字串復制到dest所指的數組中。
說明:src和dest所指內存區域不可以重疊且dest必須有足夠的空間來容納src的字串。
返回指向dest的指針。
memcpy
原型:extern void *memcpy(void *dest, void *src, unsigned int count);
{
ASSERT((dest!=NULL)(src!=NULL));
ASSERT((destsrc+count)||(srcdest+count));//防止內存重疊,也可以用restrict修飾指針
Byte* bdest = (Byte*)dest;
Byte* bsrc = http://www.nbakan8.com/sxxzx/(Byte*) src;
While(count–0)
*bdest++ = **bsrc++;
Return dest;
}
用法:#include memory.h
功能:由src所指內存區域復制count個字節到dest所指內存區域。
說明:src和dest所指內存區域不能重疊,函數返回指向dest的指針。
Memset
原型:extern void *memset(void *buffer, char c, int count);
用法:#include
功能:把buffer所指內存區域的前count個字節設置成字c。
說明:返回指向buffer的指針。
5. ASSERT()是干什麼用的
答:ASSERT()是一個調試程序時經常使用的宏,在程序運行時它計算括號內的表達式,如果表達式為FALSE (0), 程序將報告錯誤,并終止執行。如果表達式不為0,則繼續執行后面的語句。這個宏通常原來判斷程序中是否出現了明顯的數據,如果出現了終止程序以免導致嚴重后果,同時也便于查找錯誤。例如,變量n在程序中不應該為0,如果為0可能導致錯誤,你可以這樣寫程序:
……
ASSERT( n != 0);
k = 10/ n;
……
ASSERT只有在Debug版本中才有效,如果編譯為Release版本則被忽略。
assert()的功能類似,它是ANSI C標準中規定的函數,它與ASSERT的一個重要區別是可以用在Release版本中。
6. system("pause");作用?
答:系統的暫停程序,按任意鍵繼續,屏幕會打印,"按任意鍵繼續。。。。。" 省去了使用getchar();
7. 請問C++的類和C里面的struct有什麼區別?
答:c++中的類具有成員保護功能,并且具有繼承,多態這類oo特點,而c里的struct沒有
c里面的struct沒有成員函數,不能繼承,派生等等.
8. 請講一講析構函數和虛函數的用法和作用?
答:析構函數也是特殊的類成員函 數,它沒有返回類型,沒有參數,不能隨意調用,也沒有重載。只是在類對象生命期結束的時候,由系統自動調用釋放在構造函數中分配的。這種在運行時,能 依據其類型確認調用那個函數的能力稱為多態性,或稱遲后聯編。另: 析構函數一般在對象撤消前做收尾工作,比如回收內存等工作,
虛擬函數的功能是使子類可以用同名的函數對父類函數進行覆蓋,并且在調用時自動調用子類覆蓋函數,如果是純虛函數,則純粹是為了在子類覆蓋時有個統一的命名而已。
注意:子類重新定義父類的虛函數的做法叫覆蓋,override,而不是overload(重載),重載的概念不屬于面向對象編程,重載指的是存在多個同名函數,這些函數的參數表不同..重載是在編譯期間就決定了的,是靜態的,因此,重載與多態無關.與面向對象編程無關.
含有純虛函數的類稱為抽象類,不能實例化對象,主要用作接口類//
9. 全局變量和局部變量有什麼區別?是怎麼實現的?操作系統和編譯器是怎麼知道的?
答;全局變量的生命周期是整個程序運行的時間,而局部變量的生命周期則是局部函數或過程調用的時間段。其實現是由編譯器在編譯時采用不同內存分法。
全局變量在main函數調用后,就開始分配,
靜態變量則是在main函數前就已經初始化了。
局部變量則是在用戶棧中動態分配的(還是建議看編譯原理中的活動記錄這一塊)
10. 8086是多少位的系統?在數據總線上是怎麼實現的?
答:8086系統是16位系統,其數據總線是20位。
12 程序設計
1. 編寫用C語言實現的求n階階乘問題的遞歸算法:
答:long int fact(int n)
{
If(n==0||n==1)
Return 1;
Else
Return n*fact(n-1);
}
2. 二分查找算法:
1) 遞歸方法實現:
int BSearch(elemtype a[],elemtype x,int low,int high)
/*在下屆為low,上界為high的數組a中折半查找數據元素x*/
{
int mid;
if(lowhigh) return -1;
mid=(low+high)/2;
if(x==a[mid]) return mid;
if(xa[mid]) return(BSearch(a,x,low,mid-1));
else return(BSearch(a,x,mid+1,high));
}
2) 非遞歸方法實現:
int BSearch(elemtype a[],keytype key,int n)
{
int low,high,mid;
low=0;high=n-1;
while(low=high)
{
mid=(low+high)/2;
if(a[mid].key==key) return mid;
else if(a[mid].keykey) low=mid+1;
else high=mid-1;
}
return -1;
}
3. 遞歸計算如下遞歸函數的值(斐波拉契):
f(1)=1
f(2)=1
f(n)=f(n-1)+f(n-2) n2
解:非遞歸算法:
int f(int n)
{
int i,s,s1,s2;
s1=1;/*s1用于保存f(n-1)的值*/
s2=1;/*s2用于保存f(n-2)的值*/
s=1;
for(i=3;i=n;i++)
{
s=s1+s2;
s2=s1;
s1=s;
}
return(s);
}
遞歸算法:
Int f(int n)
{
If(n==1||n==2)
Rerurn 1;
Else
Rerutn f(n-1)+f(n-2);
}
4. 兩個數,不用第三塊兒內存:
答:int a = ……;
int b = ……;
a = a + b;
b = a – b;
a = a – b;
5. 冒泡排序:
答:void BubbleSort(elemtype x[],int n) //時間復雜度為0(n*n);
{
int i,j;
elemtype temp;
for(i=1;in;i++)
for(j=0;jn-i;j++)
{
if(x[j].keyx[j+1].key)
{
temp=x[j];
x[j]=x[j+1];
x[j+1]=temp;
}
}
}
//補充一個改進的冒泡算法:
void BubbleSort(elemtype x[],int n)
{
Int i,j;
BOOL exchange; //記錄標志
for(i=1;in;++i) //最多做n-1趟排序
{
Exchange = false;
For(j=n-1;j=i;–j)
{
If(x[j]x[j+1])
{
x[0] = x[j];
X[j] = x[j+1];
X[j+1] = x[0];
Exchange = true; //發生了,設置標志為真.
}
}
if (!Exchange ) //為發生替換,提前終止算法
return;
}
}
6. c語言 文件讀寫
#include "stdio.h"
main()
{
FILE *fp;
char ch,filename[10];
scanf("%s",filename);
if((fp=fopen(filename,"w")==NULL)
{
printf("cann't open filen");
exit(0);
}
ch=getchar();
while(ch!='#')
{
fputc(ch,fp);
putchar(ch);
ch=getchar();
}
fclose(fp);
}
7. winsocket編程 //這個不錯
// 代碼
#include Winsock2.h
#include stdio.h
void main()
{
WORD wVersionRequested; //版本號
WSADATA wsaData; //數據
int err;
wVersionRequested = MAKEWORD(1,1);
err = WSAStartup(wVersionRequested,wsaData);
if( err != 0)
{
return;
}
if(LOBYTE( wsaData.wVersion ) != 1||
HIBYTE( wsaData.wVersion) != 1)
{
WSACleanup();
return;
}
SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0); //建立套接字
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
bind(sockSrv,(SOCKADDR*)addrSrv,sizeof(SOCKADDR)); //綁定端口
listen(sockSrv,5); //轉換socket套接子為偵聽套接子
SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR);
while(1) //無限循環
{
SOCKET sockConn=accept(sockSrv,(SOCKADDR*)addrClient,len);
char sendBuf[100];
sprint(sendBuf,"Wel
e %s to [url]http://www.sunxin.org/[/url]",
i
_ntoa(addrClient.sin_addr));
send(sockConn,sendBuf,strlen(sendBuf)+1,0);
char recvBuf[100];
recv(sockConn,recvBuf);
printf("%sn",recvBuf);
closesocket(sockConn);
WSACleanup();
}
}
注:這是Server端;File-New-Win32 Console Application,工程名:TcpSrv;然后,File-New-C++ Source File,文件名:TcpSrv;在該工程的Setting的Link的Object/library modules項要加入ws2_32.lib
#include Winsock2.h
#include stdio.h
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1,1);
err = WSAStartup(wVersionRequested,wsaData); //啟動winsock Dll
if( err != 0)
{
return;
}
if(LOBYTE( wsaData.wVersion ) != 1||
HIBYTE( wsaData.wVersion) != 1)
{
WSACleanup();
return;
}
SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=i
_addr("127.0.0.1");
addrSrv.sin_family=AF_INET;
addrSrv.sin_port = htons(6000);
connect(sockClient,(SOCKADDR*)addrSrv,sizeof(SOCKADDR));
char recvBuf[100];
recv(sockClient,recvBuf,100,0);
printf("%sn",recvBuf);
send(sockClient,"This is zhangsan",strlen("This is zhangsan")+1,0);
closesocket(sockClient);
WSACleanup();
}
注:這是Client端;File-New-Win32 Console Application,工程名:TcpClient;然后,File-New-C++ Source File,文件名:TcpClient;同理,在該工程的Setting的Link的Object/library modules項要加入ws2_32.lib
8. 類的知識 (非常不錯的一道題目)..
C++
#include iostream.h
class human
{
public:
human(){ human_num++;}; //默認構造函數
static int human_num; //靜態成員
~human()
{
human_num–;
print();
}
void print() //
{
cout"human num is: "human_numendl;
}
protected:
private:
};
int human::human_num = 0; //類中靜態數據成員在外部定義,僅定義一次
human f1(human x)
{
x.print();
return x;
}
int main(int argc, char* argv[])
{
human h1; //調用默認構造函數,human_num變為1
h1.print(); // 打印Human_man:1
human h2 = f1(h1); //先調用函數f1(),輸出human_num:1,而后輸出human_num為0,
h2.print();//打印輸出:human_num:0
return 0;
} //依次調用兩個析構函數:輸出:human_num:-1,human_num:-2;
輸出:
1
1
0
0
-1
-2
----------------------------
分析:
human h1; //調用構造函數,—hum_num = 1;
h1.print(); //輸出:"human is 1"
human h2 = f1(h1); //再調用f1(h1)的過程中,由于函數參數是按值傳遞對象,調用默認的復制構造函數,h2并沒有調用定義的構造函數.
C/C++ 程序設計員應聘常見面試試題深入剖析
silver6 | 25 九月, 2006 09:07
本文的寫作目的并不在于提供C/C++程序員求職面試指導,而旨在從技術上分析面試題的內涵。文中的大多數面試題
各大,部分試題解答也參考了
友的意見。
許多面試題看似簡單,卻需要深厚的基本功才能給出完美的解答。企業要求面試者寫一個最簡單的strcpy函數都可看出面試者在技術上究竟達到了怎樣的程 度,我們能真正寫好一個strcpy函數嗎?我們都覺得自己能,可是我們寫出的strcpy很可能只能拿到10分中的2分。讀者可從本文看到strcpy 函數從2分到10分解答的例子,看看自己屬于什麼樣的層次。此外,還有一些面試題考查面試者敏捷的思維能力。
分析這些面試題,本身
很強的趣味性;而作為一名研發人員,通過對這些面試題的深入剖析則可進一步增強自身的內功。
2.找錯題
試題1:
void test1()
{
char string[10];
char* str1 = "0123456789"
strcpy( string, str1 );
}
試題2:
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i10; i++)
{
str1[i] = 'a'
}
strcpy( string, str1 );
}
試題3:
void test3(char* str1)
{
char string[10];
if( strlen( str1 ) = 10 )
{
strcpy( string, str1 );
}
}
解答:
試題1字串str1需要11個字節才能存放下(包括末尾的’’),而string只有10個字節的空間,strcpy會導致數組越界;
對試題2,如果面試者指出字數組str1不能在數組內結束可以給3分;如果面試者指出strcpy(string, str1)調用使得從str1內存起復制到string內存起所復制的字節數具有不確定性可以給7分,在此基礎上指出庫函數strcpy工作方式的給10 分;
對試題3,if(strlen(str1) = 10)應改為if(strlen(str1) 10),因為strlen的結果未統計’’所占用的1個字節。
剖析:
考查對基本功的掌握:
(1)字串以’’結尾;
(2)對數組越界把握的度;
(3)庫函數strcpy的工作方式,如果編寫一個標準strcpy函數的總分值為10,下面給出幾個不同得分的答案:
2分
void strcpy( char *strDest, char *strSrc )
{
while( (*strDest++ = * strSrc++) != '’ );
}
4分
void strcpy( char *strDest, const char *strSrc )
//將源字串加const,表明其為輸入參數,加2分
{
while( (*strDest++ = * strSrc++) != '’ );
}
7分
void strcpy(char *strDest, const char *strSrc)
{
//對源地址和目的地址加非0斷言,加3分
assert( (strDest != NULL) (strSrc != NULL) );
while( (*strDest++ = * strSrc++) != '’ );
}
10分
//為了實現鏈式操作,將目的地址返回,加3分!
char * strcpy( char *strDest, const char *strSrc )
{
assert( (strDest != NULL) (strSrc != NULL) );
char *address = strDest;
while( (*strDest++ = * strSrc++) != '’ );
return address;
}
從2分到10分的幾個答案我們可以清楚的看到,小小的strcpy竟然暗著這麼多玄機,真不是蓋的!需要多麼扎實的基本功才能寫一個完美的strcpy啊!
(4)對strlen的掌握,它沒有包括字串末尾的''。
讀者看了不同分值的strcpy版本,應該也可以寫出一個10分的strlen函數了,完美的版本為: int strlen( const char *str ) //輸入參數const
{
assert( strt != NULL ); //斷言字串地址非0
int len;
while( (*str++) != '' )
{
len++;
}
return len;
}
試題4:
void GetMemory( char *p )
{
p = (char *) malloc( 100 );
}
void Test( void )
{
char *str = NULL;
GetMemory( str );
strcpy( str, "hello world" );
printf( str );
}
試題5:
char *GetMemory( void )
{
char p[] = "hello world"
return p;
}
void Test( void )
{
char *str = NULL;
str = GetMemory();
printf( str );
}
試題6:
void GetMemory( char **p, int num )
{
*p = (char *) malloc( num );
}
void Test( void )
{
char *str = NULL;
GetMemory( str, 100 );
strcpy( str, "hello" );
printf( str );
}
試題7:
void Test( void )
{
char *str = (char *) malloc( 100 );
strcpy( str, "hello" );
free( str );
… //省略的其它語句
}
解答:
試題4傳入中GetMemory( char *p )函數的形參為字串指針,在函數內部修改形參并不能真正的改變傳入形參的值,執行完
char *str = NULL;
GetMemory( str );
后的str仍然為NULL;
試題5中
char p[] = "hello world"
return p;
的p[]數組為函數內的局部自動變量,在函數返回后,內存已經被釋放。這是許多程序員常犯的錯誤,其根源在于不理解變量的生存期。
試題6的GetMemory避免了試題4的問題,傳入GetMemory的參數為字串指針的指針,但是在GetMemory中執行申請內存及賦值語句
*p = (char *) malloc( num );
后未判斷內存是否申請成功,應加上:
if ( *p == NULL )
{
…//進行申請內存失敗處理
}
試題7存在與試題6同樣的問題,在執行
char *str = (char *) malloc(100);
后未進行內存是否申請成功的判斷;另外,在free(str)后未置str為空,導致可能變成一個“野”指針,應加上:
str = NULL;
試題6的Test函數中也未對malloc的內存進行釋放。
剖析:
試題4~7考查面試者對內存操作的理解程度,基本功扎實的面試者一般都能正確的回答其中50~60的錯誤。但是要完全解答正確,卻也絕非易事。
對內存操作的考查主要集中在:
(1)指針的理解;
(2)變量的生存期及作用范圍;
(3)良好的動態內存申請和釋放習慣。
再看看下面的一段程序有什麼錯誤:
swap( int* p1,int* p2 )
{
int *p;
*p = *p1;
*p1 = *p2;
*p2 = *p;
}
在swap函數中,p是一個“野”指針,有可能指向系統區,導致程序運行的崩潰。在VC++中DEBUG運行時提示錯誤“Access Violation”。該程序應該改為:
swap( int* p1,int* p2 )
{
int p;
p = *p1;
*p1 = *p2;
*p2 = p;
}
3.內功題
試題1:分別給出BOOL,int,float,指針變量 與“零值”比較的 if 語句(假設變量名為var)
解答:
BOOL型變量:if(!var)
int型變量: if(var==0)
float型變量:
const float EPSINON = 0.00001;
if ((x = – EPSINON) (x = EPSINON)
指針變量: if(var==NULL)
剖析:
考查對0值判斷的“內功”,BOOL型變量的0判斷完全可以寫成if(var==0),而int型變量也可以寫成if(!var),指針變量的判斷也可以寫成if(!var),上述寫法雖然程序都能正確運行,但是未能清晰地表達程序的意思。
一般的,如果想讓if判斷一個變量的“真”、“假”,應直接使用if(var)、if(!var),表明其為“邏輯”判斷;如果用if判斷一個數值型變 量(short、int、long等),應該用if(var==0),表明是與0進行“數值”上的比較;而判斷指針則適宜用if(var==NULL), 這是一種很好的編程習慣。
浮點型變量并不精確,所以不可將float變量用“==”或“!=”與數字比較,應該設法轉化成“=”或“=”形式。如果寫成if (x == 0.0),則判為錯,得0分。
試題2:以下為Windows NT下的32位C++程序,請計算sizeof的值
void Func ( char str[100] )
{
sizeof( str ) = ?
}
void *p = malloc( 100 );
sizeof ( p ) = ?
解答:
sizeof( str ) = 4
sizeof ( p ) = 4
剖析:
Func ( char str[100] )函數中數組名作為函數形參時,在函數體內,數組名失去了本身的內涵,僅僅只是一個指針;在失去其內涵的同時,它還失去了其常量特性,可以作自增、自減等操作,可以被修改。
數組名的本質如下:
(1)數組名指代一種數據結構,這種數據結構就是數組;
例如:
char str[10];
cout sizeof(str) endl;
輸出結果為10,str指代數據結構char[10]。
(2)數組名可以轉換為指向其指代實體的指針,而且是一個指針常量,不能作自增、自減等操作,不能被修改;
char str[10];
str++; //編譯出錯,提示str不是左值
(3)數組名作為函數形參時,淪為普通指針。
Windows NT 32位下,指針的長度(占用內存的大小)為4字節,故sizeof( str ) 、sizeof ( p ) 都為4。
試題3:寫一個“標準”宏MIN,這個宏輸入兩個參數并返回較小的一個。另外,當你寫下面的代碼時會發生什麼事?
least = MIN(*p++, b);
解答:
#define MIN(A,B) ((A) = (B) ? (A) : (B))
MIN(*p++, b)會產生宏的副作用
剖析:
這個面試題主要考查面試者對宏定義的使用,宏定義可以實現類似于函數的功能,但是它終歸不是函數,而宏定義中括弧中的“參數”也不是真的參數,在宏展開的時候對“參數”進行的是一對一的替換。
程序員對宏定義的使用要非常小心,特別要注意兩個問題:
(1)謹慎地將宏定義中的“參數”和整個宏用用括弧括起來。所以,嚴格地講,下述解答:
#define MIN(A,B) (A) = (B) ? (A) : (B)
#define MIN(A,B) (A = B ? A : B )
都應判0分;
(2)防止宏的副作用。
宏定義#define MIN(A,B) ((A) = (B) ? (A) : (B))對MIN(*p++, b)的作用結果是:
((*p++) = (b) ? (*p++) : (*p++))
這個表達式會產生副作用,指針p會作三次++自增操作。
除此之外,另一個應該判0分的解答是:
#define MIN(A,B) ((A) = (B) ? (A) : (B));
這個解答在宏定義的后面加“;”,顯示編寫者對宏的概念模糊不清,只能被無情地判0分并被面試官淘汰。
試題4:為什麼標準頭文件都有類似以下的結構?
#ifndef __INCvxWorksh
#define __INCvxWorksh
#ifdef __cplusplus
extern "C" {
#endif
/*…*/
#ifdef __cplusplus
}
#endif
#endif /* __INCvxWorksh */
解答:
頭文件中的編譯宏
#ifndef __INCvxWorksh
#define __INCvxWorksh
#endif
的作用是防止被重復引用。
作為一種面向對象的語言,C++支持函數重載,而過程式語言C則不支持。函數被C++編譯后在symbol庫中的名字與C語言的不同。例如,假設某個函數的原型為:
void foo(int x, int y);
該函數被C編譯器編譯后在symbol庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。_foo_int_int這樣的名字
了函數名和函數參數數量及類型信息,C++就是考這種機制來實現函數重載的。
為了實現C和C++的混合編程,C++提供了C連接指定號extern "C"來解決名字匹配問題,函數聲明前加上extern "C"后,則編譯器就會按照C語言的方式將該函數編譯為_foo,這樣C語言中就可以調用C++的函數了。
試題5:編寫一個函數,作用是把一個char組成的字串循環右移n個。比如原來是“abcdefghi”如果n=2,移位后應該是“hiabcdefgh”
函數頭是這樣的:
//pStr是指向以''結尾的字串的指針
//steps是要求移動的n
void LoopMove ( char * pStr, int steps )
{
//請填充…
}
解答:
正確解答1:
void LoopMove ( char *pStr, int steps )
{
int n = strlen( pStr ) – steps;
char tmp[MAX_LEN];
strcpy ( tmp, pStr + n );
strcpy ( tmp + steps, pStr);
*( tmp + strlen ( pStr ) ) = ''
strcpy( pStr, tmp );
}
正確解答2:
void LoopMove ( char *pStr, int steps )
{
int n = strlen( pStr ) – steps;
char tmp[MAX_LEN];
memcpy( tmp, pStr + n, steps );
memcpy(pStr + steps, pStr, n );
memcpy(pStr, tmp, steps );
}
剖析:
這個試題主要考查面試者對標準庫函數的熟練程度,在需要的時候引用庫函數可以很大程度上簡化程序編寫的工作量。
最頻繁被使用的庫函數包括:
(1) strcpy
(2) memcpy
(3) memset
試題6:已知WAV文件格式如下表,打開一個WAV文件,以適當的數據結構WAV文件頭并解析WAV格式的各項信息。
WAVE文件格式說明表
偏移地址
字節數
數據類型
內 容
文件頭
00H
4
Char
"RIFF"標志
04H
4
int32
文件長度
08H
4
Char
"WAVE"標志
0CH
4
Char
"fmt"標志
10H
4
過渡字節(不定)
14H
2
int16
格式類別
16H
2
int16
通道數
18H
2
int16
采樣率(每秒樣本數),表示每個通道的播放速度
1CH
4
int32
波形數據傳送速率
20H
2
int16
數據塊的調整數(按字節算的)
22H
2
每樣本的數據位數
24H
4
Char
數據標記"data"
28H
4
int32
數據的長度
解答:
將WAV文件格式定義為結構體WAVEFORMAT:
typedef struct tagWaveFormat
{
char cRiffFlag[4];
UIN32 nFileLen;
char cWaveFlag[4];
char cFmtFlag[4];
char cTransition[4];
UIN16 nFormatTag ;
UIN16 nChannels;
UIN16 nSamplesPerSec;
UIN32 nAvgBytesperSec;
UIN16 nBlockAlign;
UIN16 nBitNumPerSample;
char cDataFlag[4];
UIN16 nAudioLength;
} WAVEFORMAT;
假設WAV文件內容讀出后存放在指針buffer開始的內存單元內,則分析文件格式的代碼很簡單,為:
WAVEFORMAT waveFormat;
memcpy( waveFormat, buffer,sizeof( WAVEFORMAT ) );
直接通過訪問waveFormat的成員,就可以特定WAV文件的各項格式信息。
剖析:
試題6考查面試者數據結構的能力,有經驗的程序設計者將屬于一個整體的數據成員為一個結構體,利用指針類型轉換,可以將memcpy、memset等函數直接用于結構體地址,進行結構體的整體操作。 透過這個題可以看出面試者的程序設計經驗是否豐富。
試題7:編寫類String的構造函數、析構函數和賦值函數,已知類String的原型為:
class String
{
public:
String(const char *str = NULL); // 普通構造函數
String(const String other); // 拷貝構造函數
~ String(void); // 析構函數
String operate =(const String other); // 賦值函數
private:
char *m_data; // 用于保存字串
};
解答:
//普通構造函數
String::String(const char *str)
{
if(str==NULL)
{
m_data = http://www.nbakan8.com/sxxzx/new char[1]; // 得分點:對空字串自動申請存放結束標志''的空
//加分點:對m_data加NULL 判斷
*m_data = http://www.nbakan8.com/sxxzx/''
}
else
{
int length = strlen(str);
m_data = http://www.nbakan8.com/sxxzx/new char[length+1]; // 若能加 NULL 判斷則更好
strcpy(m_data, str);
}
}
// String的析構函數
String::~String(void)
{
delete [] m_data; // 或delete m_data;
}
//拷貝構造函數
String::String(const String other) // 得分點:輸入參數為const型
{
int length = strlen(other.m_data);
m_data = http://www.nbakan8.com/sxxzx/new char[length+1]; //加分點:對m_data加NULL 判斷
strcpy(m_data, other.m_data);
}
//賦值函數
String String::operate =(const String other) // 得分點:輸入參數為const型
{
if(this == other) //得分點:檢查自賦值
return *this;
delete [] m_data; //得分點:釋放原有的內存
int length = strlen( other.m_data );
m_data = http://www.nbakan8.com/sxxzx/new char[length+1]; //加分點:對m_data加NULL 判斷
strcpy( m_data, other.m_data );
return *this; //得分點:返回本對象的引用
}
剖析:
能夠準確無誤地編寫出String類的構造函數、拷貝構造函數、賦值函數和析構函數的面試者至少已經具備了C++基本功的60%以上!
在這個類中包括了指針類成員變量m_data,當類中包括指針類成員變量時,一定要重載其拷貝構造函數、賦值函數和析構函數,這既是對C++程序員的基本要求,也是《Effective C++》別強調的條款。
仔細學習這個類,特別注意加注釋的得分點和加分點的意義,這樣就具備了60%以上的C++基本功!
試題8:請說出static和const關鍵字盡可能多的作用
解答:
static關鍵字至少有下列n個作用:
(1)函數體內static變量的作用范圍為該函數體,不同于auto變量,該變量的內存只被分配一次,因此其值在下次調用時仍維持上次的值;
(2)在模塊內的static全局變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
(3)在模塊內的static函數只可被這一模塊內的其它函數調用,這個函數的使用范圍被限制在聲明它的模塊內;
(4)在類中的static成員變量屬于整個類所擁有,對類的所有對象只有一份拷貝;
(5)在類中的static成員函數屬于整個類所擁有,這個函數不接收this指針,因而只能訪問類的static成員變量。
const關鍵字至少有下列n個作用:
(1)欲阻止一個變量被改變,可以使用const關鍵字。在定義該const變量時,通常需要對它進行初始化,因為以后就沒有機會再去改變它了;
(2)對指針來說,可以指定指針本身為const,也可以指定指針所指的數據為const,或二者同時指定為const;
(3)在一個函數聲明中,const可以修飾形參,表明它是一個輸入參數,在函數內部不能改變其值;
(4)對于類的成員函數,若指定其為const類型,則表明其是一個常函數,不改類的成員變量;
(5)對于類的成員函數,有時候必須指定其返回值為const類型,以使得其返回值不為“左值”。例如:
const classA operator*(const classA a1,const classA a2);
operator*的返回結果必須是一個const對象。如果不是,這樣的代碼也不會編譯出錯:
classA a, b, c;
(a * b) = c; // 對a*b的結果賦值
操作(a * b) = c顯然不合編程者的初衷,也沒有任何意義。
剖析:
驚訝嗎?小小的static和const居然有這麼多功能,我們能回答幾個?如果只能回答1~2個,那還真得閉關再好好。
這個題可以考查面試者對程序設計知識的掌握程度是初級、中級還是比較深入,沒有一定的知識廣度和深度,不可能對這個問題給出全面的解答。大多數人只能回答出static和const關鍵字的部分功能。
4.技巧題
試題1:請寫一個C函數,若處理器是Big_endian的,則返回0;若是Little_endian的,則返回1
解答:
int checkCPU()
{
{
union w
{
int a;
char b;
} c;
c.a = 1;
return (c.b == 1);
}
}
剖析:
嵌入式系統者應該對Little-endian和Big-endian非常了解。采用Little- endian的CPU對操作數的存放方式是從低字節到高字節,而Big-endian對操作數的存放方式是從高字節到低字節。例如,16bit寬 的數0x1234在Little- endianCPU內存中的存放方式(假設從地址0x4000開始存放)為:
內存地址
存放內容
0x4000
0x34
0x4001
0x12
而在Big-endianCPU內存中的存放方式則為:
內存地址
存放內容
0x4000
0x12
0x4001
0x34
32bit寬的數0x12345678在Little-endianCPU內存中的存放方式(假設從地址0x4000開始存放)為:
內存地址
存放內容
0x4000
0x78
0x4001
0x56
0x4002
0x34
0x4003
0x12
而在Big-endianCPU內存中的存放方式則為:
內存地址
存放內容
0x4000
0x12
0x4001
0x34
0x4002
0x56
0x4003
0x78
聯合體union的存放順序是所有成員都從低地址開始存放,面試者的解答利用該特性,地了CPU對內存采用Little-endian還是Big-endian讀寫。如果誰能當場給出這個解答,那簡直就是一個天才的程序員。
試題2:寫一個函數返回1+2+3+…+n的值(假定結果不會超過長整型變量的范圍)
解答:
int Sum( int n )
{
return ( (long)1 + n) * n / 2; //或return (1l + n) * n / 2;
}
剖析:
對于這個題,只能說,也許最簡單的答案就是最好的答案。下面的解答,或者基于下面的解答思路去優化,不管怎麼“折騰”,其效率也不可能與直接return ( 1 l + n ) * n / 2相比!
int Sum( int n )
{
long sum = 0;
for( int i=1; i=n; i++ )
{
sum += i;
}
return sum;
}
所以程序員們需要地將數學等知識用在程序設計中。
終于明白了:按值傳遞意味著當將一個參數傳遞給一個函數時,函數接收的是原始值的一個副本。因此,如果函數修改了該參數,僅改變副本,而原始值不變。按引用傳遞意味著當將一個參數傳遞給一個函數時,函數接收的是原始值的內存地址,而不是值的副本。因此,如果函數修改了該參數,調用代碼中的原始值也隨之改變。
不管是在c/c++中還是在java函數調用都是傳值調用,.
當參數是對象的時候,傳遞的是對象的引用,這個和c/c++傳遞指針是一個道理,在函數中改變引用本身,不會改變引用所指向的對象.
華為面試題
4、SQL問答題
SELECT * FROM TABLE
和
SELECT * FROM TABLE
WHERE NAME LIKE '%%' AND ADDR LIKE '%%'
AND (1_ADDR LIKE '%%' OR 2_ADDR LIKE '%%'
OR 3_ADDR LIKE '%%' OR 4_ADDR LIKE '%%' )
的檢索結果為何不同?
答: 前者檢索全部,后者有三種情況檢索不出:NAME=null或ADDR=null或1_ADDR LIKE 2_ADDR 3_ADDR 4_ADDR其一為null.
前者檢索所有記錄,后者只能檢索出 NAME 和ADDR中非Null的記錄。
5、SQL問答題
表結構:
1、 表名:g_cardapply
字段(字段名/類型/長度):
g_applyno varchar 8;//申請單號(關鍵字)
g_applydate bigint 8;//申請日期
g_state varchar 2;//申請狀態
2、 表名:g_cardapplydetail
字段(字段名/類型/長度):
g_applyno varchar 8;//申請單號(關鍵字)
g_name varchar 30;//申請人姓名
g_idcard varchar 18;//申請人號
g_state varchar 2;//申請狀態
其中,兩個表的關聯字段為申請單號。
題目:
1、 查詢號碼為440401430103082的申請日期
select A.g_applydate
from g_cardapply A inner join g_cardapplydetail B on A.g_applyno = B.g_applyno
where B.g_idCard = '440401430103082'
2、 查詢同一個號碼有兩條以上記錄的號碼及記錄個數
select g_idCard,count(*) as Cnt from g_cardapplydetail
group by g_idcard
hng count(*) 1
3、 將號碼為440401430103082的記錄在兩個表中的申請狀態均改為07
update g_cardapplydetail set g_state = '07'
where g_idcard = '440401430103082'
update A set g_state = '07'
from g_cardapply A inner join g_cardapplydetail B on A.g_applyno = B.g_applyno
where B.g_idcard = '440401430103082'
4、
g_cardapplydetail表中所有姓李的記錄
delete from g_cardapplydetail
where g_name like '李%'
3、 將號碼為440401430103082的記錄在兩個表中的申請狀態均改為07
update g_cardapplydetail set g_state = '07'
where g_idcard = '440401430103082'
update A set g_state = '07'
from g_cardapply A inner join g_cardapplydetail B on A.g_applyno = B.g_applyno
where B.g_idcard = '440401430103082'
5、SQL問答題:
/*Select g_cardapply. g_applydate
From g_cardapply, g_cardapplydetail
Where g_cardapply. g_applyno=g_cardapplydetail. g_applyno
And g_cardapplydetail.g_idcard='440401430103082'*/
/*Select *From (select count(*) g_count , g_idcard
From g_cardapplydetail
Group by g_idcard ) a
Where a. g_count = 2*/
/*Update g_cardapply
set g_state='07'
where g_applyno in (select distinct g_applyno
from g_cardapplydetail
where g_idcard ='440401430103082')
update g_cardapplydetail
set g_state='07'
where g_idcard='440401430103082' */
/*Delete from g_cardapplydetail
Where g_name like '李%'*/
通過測試
PS:偶GF做的,自己先汗一下
金山公司幾道面試題
4. In C++, there're four type of Casting Operators, please enumerate and explain them especially the difference.
解析: C++類型轉換問題
答案: reinterpret_cast,static_cast,const_cast,dynamic_cast
static_cast 數制轉換
dynamic_cast 用于執行向下轉換和在繼承之間的轉換
const_cast 去掉const
reinterpret_cast 用于執行并不安全的orimplmentation_dependent類型轉換
7 以下代碼有什麼問題,如何修改?
#include iostream
#include vector
using namespace std;
void print(vectorint);
int main()
{
vectorint array;
array.push_back(1);
array.push_back(6);
array.push_back(6);
array.push_back(3);
//
array數組中所有的6
vectorint::iterator itor;
vectorint::iterator itor2;
itor=array.begin();
for(itor=array.begin(); itor!=array.end(); )
{
if(6==*itor)
{
itor2=itor;
array.erase(itor2);
}
itor++;
}
print(array);
return 0;
}
void print(vectorint v)
{
cout "n vector size is: " v.size() endl;
vectorint::iterator p = v.begin();
}
我的答案是,迭代器問題,只能
第一個6,以后迭代器就失效了,不能
之后的元素。
但我不知道怎麼改
void print(const vectorint);
int main()
{
vectorint array;
array.push_back(1);
array.push_back(6);
array.push_back(6);
array.push_back(3);
//
array數組中所有的6
array.erase( remove( array.begin(), array.end(), 6 ) , array.end() );
print(array);
return 0;
}
void print(const vectorint v)
{
cout "n vector size is: " v.size() endl;
copy(v.begin(), v.end(), ostream_iteratorint(cout, " ") );
}
#include iostream
#include vector
using namespace std;
int main()
{
vectorint array;
array.push_back(1);
array.push_back(6);
array.push_back(6);
array.push_back(6);
array.push_back(6);
array.push_back(6);
array.push_back(3);
array.push_back(9);
array.push_back(8);
array.push_back(5);
//Eacute;frac34;sup3;yacute;arrayEcirc;yacute;×éOuml;ETH;Euml;ùOacute;ETH;micro;Auml;6
vectorint::iterator itor;
itor=array.begin();
for(itor=array.begin(); itor!=array.end();++itor )
{
if(6==*itor)
{
itor=array.erase(itor);
–itor;
}
}
cout "vector size is: " array.size() endl;
for(itor=array.begin(); itor!=array.end();++itor )
{
cout*itor" "
}
system("pause");
return 0;
}
答案: 執行itor=array.erase(itor);這句話后,itor不會移動,而只是把
的數后面的數都往前移一位,所以
了第一個6后,指針指向第2個6,然后在來個itor++,指針就指向array.end()了,給你畫個草圖:
1 6 6 3 array.end() //最開始指針itor指向第一個6;
1 6 3 array.end() //
第一個6后,指向第二個6
1 6 3 array.end() //itor++后,就指向3了,所以不能
2. What are three ways in which a thread can enter the waiting state?
答:
CPU調度給優先級更高的thread,原先thread進入waiting
阻塞的thread或者信號,進入waiting
還有什麼
面試與被面試總結
我從事技術工作,
這幾年的面試與被面試總結
先說我去被面試的經驗吧。
回答清楚了2個問題,就能關了。
1。為什麼要離開上一家公司。
2。公司為什麼要雇傭你。
問第一個問題的是hr(或老板),呵呵 ,即使你技術過關,hr那里沒有好的影響,結果是一個字,難!
如何回答呢? hr想推論出你在他的公司能呆多久。這個時候,你甚至可以明確告訴他,我在貴公司至少能呆n(n=1)年—-當然,你沒有把握的話,絕對不能亂說,上混,要講信用的。
有一次,我就在這個問題上吃了大虧,我看公司環境還不錯,就我自做主張回答1年,結果,hr心目中是m(m=2)年,呵呵,結果可想而知了。要知道,技術面試都過關了,Hr面試是2選1,在回家的路上,我只能祈禱對手自動放棄或找到了其他更好的工作。:)
問第二個問題的是技術官。你要讓他知道你已經做過哪些商業作品。一定要是商業作品。在里面負責哪方面具體工作,對于你熟悉的地方要多說。最好就 是能爭取筆試或上機,因為用用口說的話,大家理解都不一樣,誤差可能很大,結果對你相當不利。在這個問題上我也吃過虧的,曾有一個我很看好的職位,認為把 握很大,業務理解上也很有優勢,和技術官一談,結果是game over。要知道,在其他公司的上機和筆試中,我都能在應聘者中取得高分。
再說我去面試別人的經驗吧。
當時,我的任務是出題,給分。若你覺得題很難,那麼,請千萬不要放棄,顯然,你 的對手也覺得難。只要堅持,我會認為這人有耐心很毅力,在以后的工作中也是好的合
。題一定要做完,表現出認真的態度,若有疑問或卡殼,還可以尋求面試 官的幫助,這些不會減分,相反,會增加你和他們的接觸機會,面試官會評估你的溝通能力。
有一次,有1個人來面試,題沒有完全ok,但很規范,態度很認真,他把他知道的都做上去了,我給了他技術類的高分。后來,順利進入公司,再后來進步很快,成了重要角色。
若
對你有幫助的話,請在此討論。
祝你成功
面試題
1.鏈表和數組的區別在哪里?
2.編寫實現鏈表排序的一種算法。說明為什麼你會選擇用這樣的方法?
3.編寫實現數組排序的一種算法。說明為什麼你會選擇用這樣的方法?
4.請編寫能直接實現strstr()函數功能的代碼。
5.編寫反轉字串的程序,要求優化速度、優化空間。
6.在鏈表里如何發現循環鏈接?
7.給出洗牌的一個算法,并將洗好的牌存儲在一個整形數組里。
8.寫一個函數,檢查字是否是整數,如果是,返回其整數值。(或者:怎樣只用4行代碼 ,編寫出一個從字串到長整形的函數?)
9.給出一個函數來輸出一個字串的所有排列。
10.請編寫實現malloc()內存分配函數功能一樣的代碼。
11.給出一個函數來復制兩個字串A和B。字串A的后幾個字節和字串B的前幾個字節重疊。
12.怎樣編寫一個程序,把一個有序整數數組放到二叉樹中?
13.怎樣從頂部開始逐層打印二叉樹結點數據?請編程。
14.怎樣把一個鏈表掉個順序(也就是反序,注意鏈表的邊界條件并考慮空鏈表)?
另外:
一、單項選擇題:(共12題,每題2分,共24分)
1. 下面哪一個不是C++的標準數據類型? ( D)
A. int B. char
C. bool D. real
2. break關鍵字在哪一種語法結構中不能使用? (C)
A. for語句 B. switch語句
C. if語句 D. while語句
3. 類的繼承方式有幾種? (B )
A. 兩種 B. 三種
C. 四種 D. 六種
4. extern關鍵字的作用是什麼? (D)
A. 聲明外部鏈接 B. 聲明外部頭文件引用
C. 聲明使用擴展C++語句 D. 聲明外部成員函數、成員數據。
5. C庫函數strstr的功能是? (A )
A. 查找子串 B. 計算字串長度
C. 字串比較 D. 字串
6. stl::deque是一種什麼數據類型? (A )
A. 動態數組 B. 鏈表
C. 堆棧 D. 樹
7. STL庫里含有下面的哪一種泛型算法? (D )
A. KMP查找 B. 折半查找
C. 冒泡排序 D. 快速排序
8. 現在最快且最通用的排序算法是什麼? (A )
A. 快速排序 B. 冒泡排序
C. 選擇排序 D. 外部排序
9. Win32下的線程的哪一種優先級? ( C)
A. THREAD_PRIORITY_HIGHEST 高優先級
B. THREAD_PRIORITY_IDLE 最低優先級,僅在系統空閑時執行
C. THREAD_PRIORITY_TIME_CRITICAL 優先級
D. THREAD_PRIORITY_ABOVE_NORMAL 高于普通優先級
10. 下面四個選項中,哪一個不是WinMain函數的參數? (D )
A. HINSTANCE B. INT
C. LPSTR D. WPARAM
11. VC++的編譯器中,運算new底層的實現是什麼? (B )
A. VirtualAlloc() B. HeapAlloc()
C. GlobalAlloc() D. AllocateUserPhysicalPages()
12. 下面哪一本C++參考書最厚? ( C)
A. 《Think in C++》 B. 《MFC》
C. 《C++ Primer》 D. 《Effective C++》
13. 當調用Windows API函數InvalidateRect,將會產生什麼消息(A)
A. WM_PAINT B. WM_CREATE
C. WM_NCHITTEST D. WM_SETFOCUS
14.
virtual void Draw()=0,下面說確的有幾個(C)
(1)它是純虛函數(對)
(2)它在定義它的類中不能實現(對)
(3)定義它的類不可實例化(對)
(4)如果一個類要繼承一個ADT類,必須要實現其中的所有純虛函數(錯)//可以不實現,派生之后的類仍舊作為一個抽象類.
A. 1 B. 2
C. 3 D. 4
二、不定項選擇題:(共6題,每題3分,共18分,多選、錯選、漏選均不給分)
1. vector::iterator重載了下面哪些運算? (ACD)
A. ++ B.
C. *(前置) D. ==
2. CreateFile( )的功能有哪幾個? (AB )
A. 打開文件 B. 創建新文件
C. 文件改名 D.
文件
3. 下面哪些是句柄(HANDLE)? (ABCD )
A. HINSTANCE 實例句柄B. HWND 窗口句柄
C. HDC 設備描述號句柄 D. HFONT 字體句柄
4. 下面哪些不是OpenGL標準幾何元素的繪制? (A )
A. GL_FOG B. GL_LINE_STRIP
C. GL_POINTS D. GL_TRIANGLE_FAN
5. 下面哪些運算不能被重載? (ABD )
A. 做用域運算“::” B. 對象成員運算“.”
C. 指針成員運算“-” D. 三目運算“? :”
6. 下面哪些人曾參與了世界上第一個C++編譯器的? ( )
A. Bill Gates B. Stanley Lippman
C. Anderson Hejlsberg D. Bjarne Stroustrup
7. 以下說確的是? ( ABC)
A. 頭文件中的 ifndef/define/endif 是為了防止該頭文件被重復引用。
B. 對于#include filename.h ,編譯器從標準庫路徑開始搜索 filename.h
對于#include “filename.h” ,編譯器從用戶的工作路徑開始搜索 filename.h
C. C++語言支持函數重載,C語言不支持函數重載。函數被C++編譯后在庫中的名字與C 語 言的不同。假設某個函數的原型為: void foo(int x, int y); 該函數被C編譯器編譯后在庫 中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。C++提供了C連接指定號extern“C”來解決名字匹配問 題。
D. fopen函數只是把文件目錄信息調入內存。//錯,fopen是把整個文件讀入內存
三、填空題:(共8題,每題3分,共24分)
1. 一個大小為320 X 192,顏色為灰度索引色的設備相關位圖有______字節。如果此位圖顏色為24位真彩色,則它的大小有______字節。
2. Windows API的中文意義是____ windows應用程序接口___。
3. 計算反正弦的庫函數是__asin()____;計算浮點數絕對值的庫函數是__fabs()____;計算浮點數n次方的庫函數是__pow()____;將浮點數轉化為字串的庫函數是___fcvt()___。
4. 如果i等于5,那麼( ++i ) – -的返回值是__6__。
5. API LoadBitmap()的功能是從__指定的模塊和或應用程序實例__中讀取位圖數據到內存。
6. new和__delete___對應,malloc和_free___對應,他們之間_ 不能__交叉混用。calloc的功能是__為數組動態分配內存___,realloc的功能是_改變原有內存區域的大小_。
7. SendMessage和PostMessage都會向窗體發送一個消息,但SendMessage__將一條消息發送到指定窗口,立即處理__而PostMessage__將一條消息投遞到指定窗口的消息隊列,不需要立即處理___。
8. 輸出指定圓心、半徑、邊數的圓上的點:
const int nCount = 12;
const double dOrgX = 5.0,
dOrgY = 3.0;
const double dRadius = 2.0;
for( int i = 0; i nCount; i++ )
{
double dAngle = M_PI * 2.0 / (double)nCount * i;
cout "第" i "點:X = " ________; cout ", Y = " __________ endl;
}
三、判斷題:(共12題,每題2分,共24分)
1. 一個類必須要有一個不帶參數的構造函數。 錯
2. 你不能寫一個虛的構造函數。 對
3. 類里面所有的函數都是純虛函數時才是純虛類。 錯
4. const成員函數對于任何本類的數據成員都不能進行寫操作。 對
5. 函數中帶默認值的參數必須位于不帶默認值的參數之后。 對
6. char *p = "Test" p[0] = 'R' 錯
7. cout "Test" 對
8. stl::list不支持隨機訪問疊代器。 對
9. stl::vector的效率比stl::list高。 錯
10. VC和VC++是一回事,而VC++是一種比C++更難一些的語言。 錯
11. 理論上,new和malloc造成的內存泄露都會由操作系統回收。 錯
12. 在C++中struct和class的差別很大,所以從語法上不能混用。對
四、簡述題(共3題,每題5分,共15分)
1. 請簡述PeekMessage和GetMessage的區別。
答: Peekmessage和Getmessage都是向隊列中取得消息,兩個函數的不同在于取不到消息的時候,若Getmessage()向消息 隊列中取不到消息,則程序的主線程會被OS(操作系統)掛起,等到有合適的消息時才返回;若是用Peekmessage()在消息隊列中取不到消息,則程 序會取得OS控制權,運行一段時間。
另外,在處理消息的時候,GetMessag()會將消息從隊列中
,而PeekMessage()可以設置最后一個參數wRemoveMsg來決定是否將消息保留在隊列中。
2. 請列出你所知道的在Windows SDK上,實現計時功能的方法。
答:可以使用SetTimer函數創建一個計時器,SetTimer的函數原型如下:
UINT_PTR SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc
3. 請簡述你所知道的const的各種用法。
答: const 常量
const 修飾類的數據成員
const 修飾指針
const 應用在函數聲明中
const 應用在類成員函數
五、編程題:(共3題,第1小題7分,第2小題14分,第3小題24分)
1. 深度遍歷二叉樹。
struct Node
{
Node *Parent;
Node *Left, *Right;
};
void Through(Node *Root)
{
}
2. 二分法查找。
int DicFind( int *Array, int Count, int Value )
{
}
3. 寫出字串類String的默認構造函數、析構函數和重載賦值運算。
已知類String的原型為:
class String
{
public:
String( const char *pStr = NULL ); // 默認構造函數
~String( void ); // 析構函數
String operate = ( const String Source ); // 重載賦值運算
private:
char *m_pData; // 指向字串的指針
};
今天下午的兩道面試題
1。 一人歲數的3次方是四位數,四次方是數,并知道此人歲數的3次方和4次方用遍了0~9十個數字。編寫一程序求此人的歲數。
2。對1,2,3, 4, 5 這五個數任意取出兩個數,列出他們的所有組合。
public static int getAge() {
int age;
int third;
int fourth;
for (int i = 11; true; i++) {
if (i 200) {
third = (int) Math.pow(i, 3);
fourth = (int) Math.pow(i, 4);
if (getLength(third, fourth) == 10) {
age = i;
break;
}
}
}
return age;
}
public static int getLength(int args1, int args2) {
String str1 = String.valueOf(args1);
String str2 = String.valueOf(args2);
String str = str1 + str2;
if (str.length() != 10) {
return -1;
}
int[] intarray = new int[10];
for (int i = 0; i str.length(); i++) {
intarray[i] = Integer.parseInt(str.substring(i,i+1));
}
Arrays.sort(intarray);
if(intarray[0]!=0 intarray[9]!=9)
return -1;
return 10;
}
第二題還更簡單了
for(int i=1; i6; i++){
for(int j=1; j6; j++){
if(i==j){
System.out.println(j+""+j);
}else{
System.out.println(i+""+j);
System.out.println(j+""+i);
}
}
}
public class A {
// [url]http://
munity.csdn.
/Expert/topic/4667/4667929.xml?temp=.57922[/url]
public static void main(String[] args) {
String t;
String[] s = new String[5];
int j = s.length;
for(int i=0; ij; i++) {
s[i] = new Integer(i+1).toString();
}
for(int i=0; ij; i++) {
t = s[i];
for(int a=0; aj; a++) {
t += s[i];
System.out.println(t);
}
System.out.println();
}
}
}
第二題還更簡單了
for(int i=1; i6; i++){
for(int j=1; j6; j++){
if(i==j){
System.out.println(j+""+j);
}else{
System.out.println(i+""+j);
System.out.println(j+""+i);
}
}
}
============================================================
樓上的沒看清題目,它是讓你對1,2,3, 4, 5 這五個數任意取出兩個數,列出他們的所有組合,所以重復的數字不應該算在里面。
第二題應該改為:
for(int i=1; i6; i++){
for(int j=1; j6; j++){
if(i==j){
break;
}else{
System.out.println(i+""+j);
System.out.println(j+""+i);
}
}
}
public class B {
public static void main(String[] args) {
for (int i = 1; i 6; i++) {
int t = i;
for(int a = 0; a5; a++) {
int c = a+1;
if(c == t) {
continue;
}else {
System.out.println(t*10+c);
}
}
System.out.println();
}
}
}
第二題
public class Test
{
public static void main(String[] args)
{
int[][] a=new int[5][];
for(int i=0;ia.length;i++)
{
a[i]=new int[i+1];
}
for(int i=1;i=a.length;i++)
{
for(int j=i+1;j=a.length;j++)
{
System.out.print(i);
System.out.print(j+" ");
}
System.out.print(" ");
}
for(int i=a.length;i0;i–)
{
for(int j=i-1;j0;j–)
{
System.out.print(i);
System.out.print(j+" ");
}
System.out.print(" ");
}
}
}
public class Test {
public static int getDigits(String str) {
int[] intarr = new int[10];
for (int i = 0; i 10; i++)
intarr[i] = 0;
for (int i = 0; i str.length(); i++) {
int j = Integer.parseInt(str.substring(i, i + 1));
intarr[j] = 1;
}
int num = 0;
for (int i = 0; i 10; i++)
num = num + intarr[i];
return num;
}
private static int getAge() {
int age;
int third;
int fourth;
for (age = 1; age 100; age++) {
third = (int) Math.pow(age, 3);
fourth = (int) Math.pow(age, 4);
if (third 1000 || third = 10000)
continue;
if (fourth 100000 || fourth = 1000000)
continue;
String str = String.valueOf(third) + String.valueOf(fourth);
if (getDigits(str) == 10)
return age;
}
return 0;
}
}
第二道題
class Combine
{
public static void main(String[] args)
{
for(int i=1; i5; i++)
{
for(int j=i+1; j6; j++)
{
System.out.println(i+""+j);
System.out.println(j+""+i);
}
}
}
public class Age
{
public static void main(String [] args)
{
String str1 = null;
String str2 = null;
String str3 = null;
String str4 = "0123456789"
for(int i=10;i50;i++)
{
str1 = Integer.toString(i*i*i);
str2 = Integer.toString(i*i*i*i);
str3 = str1+str2;
if((str1.length() == 4) (str2.length() ==6))
{
boolean flag = true;
for(int j=0;j10;j++)
if(str3.indexOf(str4.charAt(j))==-1)
flag = false;
if(flag){
System.out.println(""+i);
System.out.println(str3);
}
}
}
}
}
比賽貼~微軟又一道筆試題
silver6 | 04 四月, 2006 09:48
怎樣只用4行代碼編寫出一個從字串到長整形的轉換函數?
我的方法,不過好象比4行多 *_#!~
long atol(char *str)
{
char c = *str;
if( !isdigit(c) ) str++;
for(long value = http://www.nbakan8.com/sxxzx/0; *str != '' value = https://jixiaotop.com/id/value * 10 + (*str -'0'),str++);
return c == '-' ? -value : value ;
}
void stol(const char * des, long num)
{
for (int base = 1, i = 0; des[i] != '' base = 10, ++i)
{
num *= base;
num += (int)(des[i] – '0');
}
}
num 要初始化為0
void stol(const char * des, long num)
{
for (int i=num=0; des[i] != '' i++)
{
num *= 10;
num += (int)(des[i] – '0');
}
}
void stol(char *str, long num)
{
while(*str != '')
{
num = num * 10 + (*str – '0');
str++;
}
}
void stol(const char * des, long num)
{
char p = des[0];
for (int b = 1, pos = 1, base = 1; des[pos] != '' b = 10, ++pos, base *= 10)
{
(num *= b) += (int)(des[pos] – '0');
}
p == '-' ? (num *= -1) : (num = (int)(des[0] – '0') * base + num);
}
改了一下
真的是微軟的筆試題麼?
我只用了一行。
#include iostream
using namespace std;
long str2long(char* p,long xxx=0L)
{
return *p==''?xxx:str2long(p,xxx*10+(*p+++0-'0'));
}
int main()
{
char *str="123456789",*p=str;
coutstr2long(p);
getchar();
return 0;
}
用STL,四行
#include sstream
#include iostream
#include string
using namespace std;
long ToLong(string s)
{
long l;
istringstream iss(s);
issl;
return l;
}
int main(int argc, _TCHAR* argv[])
{
string s = "-12356"
coutToLong(s);
return 0;
}
謝謝剛才上面的帖子提醒負數的問題,我更正了,還是只用一行:
#include iostream
using namespace std;
long str2long(char* p,long xxx=0L,bool IsPositive=true)
{
return *p==''?(IsPositive?xxx:xxx*(-1)):(*p=='-'?str2long(++p,0L,false):str2long(p,xxx*10+*p+++0-'0',IsPositive));
}
int main()
{
char *str="-123456789",*p=str;
coutstr2long(p);
getchar();
return 0;
}
C語言面試題總匯
4. static有什麼用途?(請至少說明兩種)
1.限制變量的作用域
2.設置變量的存儲域
7. 引用與指針有什麼區別?
1) 引用必須被初始化,指針不必。
2) 引用初始化以后不能被改變,指針可以改變所指的對象。
2) 不存在指向空值的引用,但是存在指向空值的指針。
8. 描述實時系統的基本特性
在特定時間內完成特定的任務,實時性與可靠性
9. 全局變量和局部變量在內存中是否有區別?如果有,是什麼區別?
全局變量儲存在靜態數據庫,局部變量在堆棧
10. 什麼是平衡二叉樹?
左右子樹都是平衡二叉樹 且左右子樹的深度差值的絕對值不大于1
11. 堆棧溢出一般是由什麼原因導致的?
沒有回收
12. 什麼函數不能聲明為虛函數?
constructor
13. 冒泡排序算法的時間復雜度是什麼?
O(n^2)
14. 寫出float x 與“零值”比較的if語句。
if(x0.000001x-0.000001)
16. Inter
采用哪種
絡協議?該協議的主要層次結構?
tcp/ip 應用層/傳輸層/
絡層/數據鏈路層/物理層
17. Inter
物理地址和IP地址轉換采用什麼協議?
ARP (Address Resolution Protocol)(地址解析協議)
18.IP地址的編碼分為哪倆部分?
IP地址由兩部分組成,
絡號和主機號。不過是要和“子
掩碼”按位與上之后才能區分哪些是
絡位哪些是主機位。
2.用戶輸入M,N值,從1至N開始順序循環數數,每數到M輸出該數值,直至全部輸出。寫出C程序。
循環鏈表,用取余操作做
3.不能做switch()的參數類型是:
switch的參數不能為實型。
華為
1、局部變量能否和全局變量重名?
答:能,局部會全局。要用全局變量,需要使用"::"
局部變量可以與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。對于有些編譯器而言,在同一個函數內可以定義多個同名的局部變量,比如在兩個循環體內都定義一個同名的局部變量,而那個局部變量的作用域就在那個循環體內
2、如何引用一個已經定義過的全局變量?
答:extern
可以用引用頭文件的方式,也可以用extern關鍵字,如果用引用頭文件方式來引用某個在頭文件中聲明的全局變理,假定你將那個變寫錯了,那麼在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那麼在編譯期間不會報錯,而在連接期間報錯
3、全局變量可不可以定義在可被多個.C文件
的頭文件中?為什麼?
答:可以,在不同的C文件中以static形式來聲明同名全局變量。
可以在不同的C文件中聲明同名的全局變量,前提是其中只能有一個C文件中對此變量賦初值,此時連接不會出錯
4、語句for( ;1 ;)有什麼問題?它是什麼意思?
答:和while(1)相同。
5、do……while和while……do有什麼區別?
答:前一個循環一遍再判斷,后一個判斷以后再循環
6、請寫出下列代碼的輸出內容
#includestdio.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 + DATE2
本文來自:解夢佬,原地址:https://www.jiemenglao.com/suanming/415550.html