這些c語言經典筆試題,你做過了嗎?讓我們一起來看看吧!
創新互聯2013年至今,是專業互聯網技術服務公司,擁有項目成都網站建設、做網站網站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元雨山做網站,已為上家服務,為雨山各地企業和個人服務,聯系電話:18982081108題目1 代碼#define _CRT_SECURE_NO_WARNINGS 1
#include#include#includevoid GetMemory(char* p)
{
p = (char*)malloc(100);
}
void Test(void)
{
char* str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}
int main() {
Test();
return 0;
}
分析拿到代碼的第一步,讓我們先來看main函數。main函數調用了無參的Test函數,因此,我們轉而去看Test()函數中的內容。(注意:不要一上來就去看功能函數,這樣也許會遺漏main函數中的一些操作,導致分析出現偏差!)
粗看Test函數,我們可以很容易分析出其功能為字符數組str在內存中開辟一塊空間,將hello world字符串拷貝到str中并打印出來。乍一看,Test函數中并沒有問題,但是,你有沒有隱隱約約覺得有些奇怪呢?再看看在Test函數中被調用的GetMemory函數,或許你會發現錯誤之處。
GetMemory函數的參數是char* p,看到這里,你是否找到了錯誤?
如下圖所示,這道題的錯誤在于,這里的傳參過程是值拷貝,也即,形參p是實參str的一份臨時拷貝,所以,p使用malloc函數開辟的內存空間str是拿不到的,函數執行完成返回Test函數后,str依然是空指針,而對空指針調用strcpy函數會報錯導致程序崩潰。
你以為到這里就結束了嗎?細心的小伙伴也許還發現了另外一個錯誤,那就是內存泄漏。這段程序中調用了malloc函數,卻沒有調用free函數。而且,更為嚴重的問題是,即使調用了free(str);這個問題依然沒有得到解決。
當GetMemory函數執行結束后,p作為形參被釋放,而p指向的那塊malloc出的一塊內存空間將再也找不到了,既然無法得知地址,自然也就無法釋放了,由此造成內存泄漏。
修改代碼之前,我們分析出這段代碼存在兩處錯誤,值傳遞和內存泄漏,因此,修改時也應該針對這兩個問題進行改動。
但注意:
修改時不應該改變原程序的思路。因此,不使用GetMemory函數,直接在Test函數中開辟空間的做法是不合適的。
在修改時,首先將值傳遞改為地址傳遞,傳參時使用&str,而&str的類型為char**,因此GetMemory函數的形參也要做相應處理。
同時,在開辟空間之后,我們可以進一步優化代碼,即加上對malloc函數的判斷,當malloc失敗時對用戶進行提示。
在Test函數中,同樣應該做出判斷,當str不為空時才執行strcpy函數,打印字符串并釋放malloc開辟的空間。
使用后也不要忘記使用free函數釋放空間,并將指針置空
#define _CRT_SECURE_NO_WARNINGS 1
#include#include#includevoid GetMemory(char** p)
{
*p = (char*)malloc(100);
if (*p == NULL) {
printf("開辟失敗\n");
}
}
void Test(void)
{
char* str = NULL;
GetMemory(&str);
if (!str) {
strcpy(str, "hello world");
printf(str);
free(str);
? ? ? ? str=NULL;
}
}
int main() {
Test();
return 0;
}
運行結果修改前:程序直接崩潰
修改后:正常輸出hello world
題目2 代碼char* GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();
printf(str);
}
int main() {
Test();
return 0;
}
分析這道題的錯誤是非法訪問內存。
在GetMemory函數中,p是一個char數組形參,當這個函數執行結束后,p就被銷毀了。但是,函數最后一句是 return p,而返回值為char*,所以此時的p為指向數組首元素的指針。將這個指針指向的地址賦給str后再打印,就構成了非法訪問內存。
修改將char p[] 改成char* p,p存放的就是常量字符串的地址,即使出了GetMemory函數,這個常量字符串依然存在。
char* GetMemory(void)
{
char* p = "hello world";
return p;
}
void Test(void)
{
char* str = NULL;
str = GetMemory();
printf(str);
}
int main() {
Test();
return 0;
}
運行結果修改前:
修改后:
題目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);
}
int main() {
Test();
return 0;
}
分析拿到這道題之后,你是不是大致看完卻發現好像沒有什么問題,運行后的結果也是正確的。那這道題的問題究竟在哪呢?
這道題的問題并不大,但卻很重要。答案是,內存泄漏。
這段程序中調用了malloc函數,卻沒有調用free函數,導致在GetMemory中開辟的空間無法釋放。
修改只需要在代碼最后加上free函數即可。
void GetMemory(char** p, int num)
{
*p = (char*)malloc(num);
}
void Test(void)
{
char* str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
? ? free(str);
? ? str=NULL;
}
int main() {
Test();
return 0;
}
運行結果修改前:
修改后:
題目4 代碼void Test(void)
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
free(str);
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
int main() {
Test();
return 0;
}
分析這道題在分析時很容易看出錯誤,但在修改時卻有一絲難度。
從代碼中可以分析出,這道題的問題在于在free(str)后還使用str,雖然最后的結果看似正常,但已經構成了非法訪問內存的錯誤
修改在修改時,我相信絕大多數小伙伴會選擇直接將free移到最后,如下:
void Test(void)
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
? ? free(str);
}
int main() {
Test();
return 0;
}
但是,這樣修改之后卻顯得有些奇怪,前一句strcpy(str, "hello");明確表示str里此時是有數據的,再判斷str != NULL不是多此一舉嗎?難道要將這些都刪去?
還記得我們之前提過的原則么,盡量不要改變代碼原來的思路,因此,這個方法是不合適的。
正確的修改方法是:在用free函數釋放開辟的空間之后就立即將str置空,這樣既保證了代碼的邏輯未被修改,又解決了非法訪問內存的問題。
void Test(void)
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
? ? free(str);
? ? str==NULL;
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
int main() {
Test();
return 0;
}
運行結果修改前:
修改后:
你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
網站標題:[C語言]經典筆試題-創新互聯
分享鏈接:http://vcdvsql.cn/article30/hseso.html
成都網站建設公司_創新互聯,為您提供網站內鏈、移動網站建設、商城網站、手機網站建設、企業建站、網站設計公司
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯