C語言面試題大彙總 (影象處理方向)
template能實現抽象和效率的結合;同時template還能有效地防止程式碼膨脹) 16.談談Windows DNA結構的特點和優點。 答:Windows Distributed interNet Application Architecture(Windows分散式應用結構,簡稱Windows DNA)是微軟建立新一代高適應性商業解決方案的框架,它使公司能夠充分地挖掘數字神經系統的優點。Windows DNA是第一個將Internet、客戶/伺服器、和用於計算的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;i<N;++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 (x>>N==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; 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。 注意:陣列名作為函式引數時,退化為指標. 陣列名作為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 ————即使你是個程式設計高手,你在面試前也應該要看看這套題,她也許會給你帶來好運,否則你有可能後悔當初為什麼沒有看而跳樓自殺,這樣我會很內疚的。這套題看似簡單,但你未必能得高分,即使你看不懂也要把她背下來! 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就只能拷貝字串了,它遇到'/0'就結束拷貝;例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字串長度(第一個'/0'之前)是否超過50位,如超過,則會造成b的記憶體地址溢位。 strcpy 原型:extern char *strcpy(char *dest,char *src); { ASSERT((dest!=NULL)&&(src!=NULL)); Char *address = dest; While((*dest++=*src++)!=’/0’) 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((dest>src+count)||(src>dest+count));//防止記憶體重疊,也可以用restrict修飾指標 Byte* bdest = (Byte*)dest; Byte* bsrc = (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(low>high) return -1; mid=(low+high)/2; if(x==a[mid]) return mid; if(x<a[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].key<key) low=mid+1; else high=mid-1; } return -1; } 3. 遞迴計算如下遞迴函式的值(斐波拉契): f(1)=1 f(2)=1 f(n)=f(n-1)+f(n-2) n>2 解:非遞迴演算法: 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;i<n;i++) for(j=0;j<n-i;j++) { if(x[j].key>x[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;i<n;++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]; inet_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=inet_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_num<<endl; } 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; i<10; 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)字串以’/0’結尾;
(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同樣的問題,在執行
相關推薦
C語言面試題大彙總 (影象處理方向)
1、區域性變數能否和全域性變數重名? 答:能,區域性會遮蔽全域性。要用全域性變數,需要使用"::" ;區域性變數可以與全域性變數同名,在函式內引用這個變數時,會用到同名的區域性變數,而不會用到全域性變數。對於有些編譯器而言,在同一個函式內可以定義多個同名的區域性變數,比如在兩個迴圈體內都定義一個同名的
C語言面試題大彙總之華為面試題
7. 以下說法正確的是? ( ABC) A. 標頭檔案中的 ifndef/define/endif 是為了防止該標頭檔案被重複引用。 B. 對於#include <filename.h> ,編譯器從標準庫路徑開始搜尋 filename.h 對於#include “filename.
C語言面試題---指標篇(三)
版本宣告:本文轉載於公眾號TeachPlus C語言面試題---指標篇(三) 了解了記憶體空間,接下來我們就一起看一下指標自身用法的一些題目,先來看這樣一道題目: 分析下面程式碼:` # include <stdio.h> # include
C語言面試題---指標篇(一)
版本宣告:本文轉載於公眾號TeachPlus 指標的使用,一直是c語言面試題中必考的部分, 因為指標本身使用的複雜性與普適性,所以考點非常多,而且也可以與其他知識相互結合, 因此我們將會使用五篇專題的篇幅來介紹指標。分析下面的程式,指出程式中的錯誤:
C語言面試題---指標篇(二)
# include <stdio.h># include <stdlib.h># include <string.h>void getMemory( char **p , int num){ *p = malloc(num);} int main() {
C語言面試題---指標篇(四)
解析:首先看最後一個問題, c 是第一個元素的地址, *c 是第一行元素的首地址,其實第一行元素的地址就是第一個元素的地址, **c 是提取第一個元素。為什麼 c , *c 的值相等?c是陣列名,是一個二維指標,它的值就是陣列的首地址,也即第一行元素的首地址(等於 *c ),也等於第一行第一個元素
C語言面試題 4 (查詢整數陣列中第二大的數)
題目:寫一個函式找出一個整數陣列中,第二大的數。【Mirosoft】 PS:1、” 66,66,66,66,66 ”,則沒有第二大數。 2、” 99,99,88,86,68,66 ”,則最大數是88。 下面我先給出查詢最大數字的程式: int GetFirstMaxNumbe
C/C++面試題大彙總之 基本問題
1.new、delete、malloc、free關係 delete會呼叫物件的解構函式,和new對應free只會釋放記憶體,new呼叫建構函式。malloc與free是C++/C語言的標準庫函式,new/delete是C++的運算子。它們都可用於申請
C/C++面試題大彙總
原文地址: 前處理器(Preprocessor) 1 . 用預處理指令#define 宣告一個常數,用以表明1年中有多少秒(忽略閏年問題) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在這想看到幾件事
C語言面試題分類->排序算法
OS sort 試題 時間復雜度 ups popup popu 使用 body 1.選擇排序。 每次將最小的數,與剩余數做比較。找到更小的,做交換。 時間復雜度:O(n2) 空間復雜度:O(1) 優缺點:耗時但內存空間使用小。 void selectSor
C語言面試題分類->回調
指向 name 傳輸 join 接口 但是 PE AS 一個數 本文主要講解如果實現回調,特別是在封裝接口的時候,回調顯得特別重要,我們首先假設有兩個程序員在寫代碼,A程序員寫底層驅動接口,B程序員寫上層應用程序,然而此時底層驅動接口A有一個數據d需要傳輸給B,此時有兩種方
智郵普創c語言面試題 ---- 字母概率
arr apple void != stdio.h app words 遊戲 包含 題目描述 小明最近對概率問題很感興趣。一天,小明和小紅一起玩一個概率遊戲,首先小明給出一個字母和一個單詞,然後由小紅計算這個字母在這個單詞中出現的概率。字母不區分大小寫。 例如,給定的字母是
C語言面試題2
1 預處理 問題1:什麼是預編譯?何時需要預編譯? 答: 預編譯又稱預處理,是整個編譯過程最先做的工作,即程式執行前的一些預處理工作。主要處理#開頭的指令。如拷貝#include包含的檔案程式碼、替換#define定義的巨集、條件編譯#if等。. 何時需要預編譯: 1、總是使用不經常改動的
Java開發面試題大彙總,年薪30萬的面試題你能答出多少?
最近有很多朋友在問,年後打算跳槽,這兩個月該怎麼準備,針對這些問題,我總結了一套年薪30萬左右Java開發面試題,雖然還落了一下沒寫,但是我感覺完全掌握這些,年薪30萬是沒有問題的,下面來看看這些面試題你能答出多少。 一、Java基礎 1. String類為什麼是fina
100道c語言面試題
題目來源: 1、中興、華為、慧通、英華達、微軟亞洲技術中心等中 外企業面試題目; 2、C 語言面試寶典(林銳《高質量程式設計第三版》)。 說明: 1、部分C 語言面試題中可能會參雜部分和C++ 相關的知 識,為了保持題目的靈活性故保留,但選題最終還是 會以C
C語言面試題
關於“一年有多少秒”的巨集定義 網上關於這個問題的答案都是(365*24*60*60)UL,是錯誤的。 正解:數字和型別是一個整體,()是外人。 #include <stdio.h> #define SECONDS_PER_YEAR (3
9道常見C語言面試題
1、區域性變數能否和全域性變數重名? 答:能,區域性會遮蔽全域性。要用全域性變數,需要使用"::" ;區域性變數可以與全域性變數同名,在函式內引用這個變數時,會用到同名的區域性變數,而不會用到全域性變數。對於有些編譯器而言,在同一個函式內可以定義多個同
《劍指offer》面試題答案彙總(Java版)
面試題2:實現Singleton模式 (1)餓漢模式 public class Singleton{ private static Singleton instance = new Singleton(); private Singleton(){}
12個有趣的C語言面試題(中英文對照)
In this article, we will discuss some interesting problems on C language that can help students to brush up their C programming skills
c語言面試題1
> 前處理器(Preprocessor) 1. 用預處理指令#define 宣告一個常數,用以表明1年中有多少秒(忽略閏年問題) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在這想看到幾件事情: 1).