1. 程式人生 > >C/C++ 面試題 (收集)

C/C++ 面試題 (收集)

1, 計算sizeof表示式和strlen表達的值(32位作業系統)。

	char s1[] = “”;			
	char s2[] = “Hello World”;
	char *p = s2;
	char *q = NULL;
	void *r = malloc(100);
sizeof(s1) = 1;  sizeof(s2) = 12;  sizeof(p) = 4;  sizeof(q) = 4; sizeof(r) = 4;
strlen(s1) = 0;  strlen(s2) = 11;  strlen(p) = 11;  strlen(q) = 沒有輸出; sizeof(r) 從void* 到 const char* 轉換失敗;
	char s1[10] = {‘m’, ‘o’, ‘b’, ‘I’, ‘l’};
	char s2[20] = {‘A’, ‘N’, ‘S’, ‘I’, ‘\0’, ‘C’, ‘+’, ‘+’};
	char s3[6]= {‘I, ‘S’, ‘O’, ‘C’, ‘+’, ‘+’};
strlen(1) = 5;  strlen(s2) =4;  sizeof(s3) = 不確定;
說明:  sizeof : 查詢物件或型別的大小, 位元組數; strlen : 返回所給位元組字串的長度, 在一個字元陣列中,字元的數量是從指標或陣列中第一個元素至遇到且不包括第一次出現的null 字元。
2,請填寫bool, float, 指標變數與 “零值” 比較的if語句.
  bool flag 與 “零值” 比較的 if 語句:
	if(flag)
	if(!flag)
  float x 與 “零值” 比較的 if 語句:
	// 精度EPSILON根據應用要求而定
	Const float EPSILON = 1e-6;
	if( (x >= -EPSILON) && (X <= EPSILON) )       
  char *p 與 “零值” 比較的 if 語句:
	if(p == NULL)
	if(p != NULL)
3,(1)標頭檔案中的Ifndef/define/endif的作用是什麼?
防止該標頭檔案被重複引用或編譯.
  (2)#include <filename.h> 和 #include “filename.h” 有什麼區別?
對於#include <filename.h>, 編譯器從開發環境設定的路徑開始搜尋filename.h;
對於#include “filename.h”, 編譯器從使用者的工作路徑開始搜尋filename.h。

4,const 有什麼用途?
(1)可以定義 const 常量;
(2) Const 可以修飾函式的引數、返回值及函式的定義體(在c++中)。被 const 修飾的物件都受到強制保護,可以預防意外的修改,提高程式的健壯性。

5,在C++ 程式中呼叫被C 編譯器編譯後的函式, 為什麼要加 extern “C” ?
C++ 語言支援函式過載,C 語言不支援函式過載。函式被 C++ 編譯器和被 C
編譯器編譯後生成的內部名字是不同的。假設某個函式的原型為:void foo(int x, int y); 該函式被 C 編譯器編譯後的內部名字為_foo, 而C++ 編譯器會產生如_foo_int_int 之類的名字。C++ 提供了 C 連線交換指定符號 extern “C” 來解決名字匹配問題。

6,請簡述以下連個 for 迴圈的優缺點。
(1)
	for(i=0; i < N; i++)
	{
		if(condition)
			DoSomething();
		else
			DoOtherthing();	
	}
優點:程式簡潔。
缺點:多執行了 N-1 次邏輯判斷,並且打斷了迴圈 “流水線” 作業, 使得編譯器不能對迴圈進行優化處理,降低了效率。

(2)
	if(condition)
	{
		for(i=0; i<N; i++)
			DoSomething();
	}
	else
	{
		for(i=0; i<N; i++)
			DoOthering();
	}
優點:迴圈的效率高。

缺點:程式不簡潔。

7,回答下面的程式執行會出現什麼樣的結果(記憶體問題)。

(1)

	void GetMemory(char *p)
	{
		p = (char*) malloc(100);
	}
	void Test(void)
	{
		char *str = NULL;
		GetMemory(str);
		strcpy(str, "hello world");
		printf(str);
	}

請問執行Test函式會有什麼樣的結果?
程式崩潰。
因為 GetMemory 並不能傳遞動態記憶體,Test 函式中的 str 一直都是 NULL。strcpy(str, "hello world");

將使程式崩潰。

        (2) 

	char *GetMemory(void)
	{
		char p[] = "hello world";
		return p;
	}
	void Test(void)
	{
		char *str = NULL;
		str = GetMemory();
		printf(str);
	}

請問執行Test函式會有什麼樣的結果?
可能是亂碼。
因為 GetMemory 返回的是指向“棧記憶體” 的指標,該指標的地址不是 NULL,
但其原有的內容已經被清除,新內容不可知

(3) 
	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函式會有什麼樣的結果?
(1)能夠輸出“hello”。
(2)記憶體洩漏。

(4) 

	void Test(void)
	{
		char *str = (char*) malloc(100);
		strcpy(str, "hello");
		free(str);
		if(str != NULL)
		{
			strcpy(str, "world");
			printf(str);
		}
	}
請問執行Test函式會有什麼樣的結果?
篡改動態記憶體區的內容, 後果難以預料,非常危險。因為free(str); 之後,str成為野指標,
if(str != NULL) 語句不起作用。

8, 型別轉換

	double d =100.25;
	int x = d;
	int *pInt = (int *)&d;
請問以下兩個輸出語句的結果是否相同?為什麼?
	cout << x << endl;
	cout << *pInt << endl;
兩個輸出結果不相同。第一個結果為100,x 取 d 的整數部分;
第二個結果不是100,*pInt 等於 d 的前4位元組的數值,而不是 d 的整數部分。

9, 編寫 strcpy 函式。
已知 strcpy 函式原型為:char *strcpy(char *strDest, const char *strSrc);
其中,strDest 是目的字串,strSrc 是源字串。
(1)不呼叫 C/C++ 的字串庫函式,請編寫函式 strcpy :
	char *strcpy(char *strDest, const char *strSrc)
	{
		assert( (strDest != NULL)&&(strSrc != NULL) );
		char *address = strDest;
		while( (*strDest++ = *strSrc++) != '\0')
			NULL;
		return address;
	}
(2)strcpy 能把 strSrc 的內容複製到 strDest,為什麼還要 char* 型別的返回值?
為了實現鏈式表示式。例如:int length = strlen(strcpy(strDest, "hello world"));

10,編寫類 String 的建構函式、解構函式和賦值函式。

	//String 的普通建構函式
	String::String(const char *str): m_pData(NULL)
	{
		if(str == NULL)
		{
			m_pData = new char[1];
			*m_pData = '\0'
		}
		else
		{
			int length = strlen(str);
			m_pData = new char[length+1];
			strcpy(m_pData, str);
		}
	}
	//String 的解構函式
	String::~String(void)
	{
		delete []m_pData;
		m_pData = NULL;
	}
	//String 的拷貝建構函式
	String::String(const String &other)
	{
		int length = strlen(other.m_pData);
		m_pData = new char[length+1];
		strcpy(m_pData, other.m_pData);
	}
	//賦值函式
	String &String::operator =(const String &other)
	{
		if(this != &other)
		{
			char *pTemp =new char[strlen(other.m_pData)+ 1];
			strcpy(pTemp, other.m_pData);
			delete []m_pData;
			m_pData = pTemp;
		}
		return *this;
	}
11、程序和執行緒關係與區別
執行緒和程序的區別有,具體有以下 3 個方面:
(1)一個程式至少有一個程序,一個程序至少有一個執行緒;
(2)程序在執行過程中擁有獨立的記憶體單元,而多個執行緒共享程序所擁有的記憶體;
(3)程序可以獨立執行,但執行緒不能夠獨立執行,必須依存在程序中,由使用該程序的應用程式提供多個執行緒執行控制。

程序為應用程式的執行例項,是應用程式的一次動態執行。程序是由程序控制塊、程式段、資料段3部分組成。一個程序可以包含若干執行緒,使用執行緒可以實現應用程式同時做幾件事並且互相不干擾。程序是作業系統進行資源分配的單位。

執行緒是程序中的一個實體,是被系統獨立排程和分派的基本單位,執行緒自己不擁有系統資源,只擁有一點在執行中必不可少的資源。執行緒與同屬一個程序的其他執行緒共享程序所擁有的全部資源。一個執行緒可以建立和撤銷另一個執行緒,同一程序中的多個執行緒之間可以併發執行。