在后面的五篇中,我們開始重點介紹一些C語言編程中的技巧和常見的錯誤伟恶。這些會對大家今后的面試和工作起到一些積極的作用宵晚。
1. 特殊比較
在程序設(shè)計中,很常見的一個問題是變量與零值的比較問題筋讨。很多資深程序員還經(jīng)常在這個問題上犯錯。
1.1 float類型與零值比較
也許大家不假思索就會寫出這樣的代碼:
float x;
...
if (x == 0.0)
if (x != 0.0)
如果你面試的時候?qū)懗鲞@樣的代碼摸恍,很遺憾你沒被錄取悉罕。一段簡單的代碼就能說明這種寫法有什么問題:
#include <stdio.h>
int main()
{
float b = 0.01;
float x = b - 0.01;
if (x == 0.0)
{
printf("Yes");
}
else
{
printf("No");
}
return 0;
}
我們看一下這段代碼的執(zhí)行結(jié)果:
看了執(zhí)行結(jié)果,也許你會很奇怪立镶。為什么打印的結(jié)果不是Yes呢壁袄?其實,在內(nèi)存中保存0.01這樣一個數(shù)字時媚媒,計算機其實保存的數(shù)字是0.00999999978嗜逻。因此,在執(zhí)行b - 0.01這句代碼時結(jié)果并不是0而是2.23517413e-10缭召。具體原因我們就不在這里討論了栈顷。那正確的寫法究竟是什么呢逆日?正確的寫法如下:
#include <stdio.h>
#define EPSINON 0.00001
int main()
{
float b = 0.01;
float x = b - 0.01;
if ((x >= -EPSINON) && (x <= EPSINON))
{
printf("Yes");
}
else
{
printf("No");
}
printf("\n");
return 0;
}
這樣寫通過一個精確范圍來界定x變量是否為0。
1.2 空字符串判斷
前些天組里還有位資深程序員寫出了類似下面的代碼萄凤,大家覺得有什么問題室抽。
int main()
{
char* pch = (char*)malloc(5 * sizeof(char));
pch[0] = 0;
if (pch == "")
{
printf("Yes");
}
else
{
printf("No");
}
return 0;
}
寫這段代碼的人認為通過pch[0] = 0這句話把pch變成了一個空字符串,之后在pch == ""這句判斷語句執(zhí)行時結(jié)果應(yīng)該為真靡努。因此坪圾,應(yīng)該打印"Yes",結(jié)果打印的卻是"No"惑朦。
原因其實很簡單兽泄,pch == ""這句話其實比較的是pch指針和“”這個空字串地址。兩個不同的地址比較結(jié)果跟保存內(nèi)容其實沒有任何關(guān)系漾月。正確的寫法應(yīng)該是這樣:
int main()
{
char* pch = (char*)malloc(5 * sizeof(char));
pch[0] = 0;
if (strcmp(pch, "") == 0)
{
printf("Yes");
}
else
{
printf("No");
}
return 0;
}
C語言庫函數(shù)中為大家提供了strcmp這么一個無比好用的函數(shù)病梢,那么一定要學(xué)會正確使用它。
2. 變量的內(nèi)存空間
在C語言程序設(shè)計中栅屏,經(jīng)常需要關(guān)注變量在內(nèi)存中的狀態(tài)飘千。其中,非常重要的是占用內(nèi)存的大小栈雳。常用sizeof()這個函數(shù)來得到占用內(nèi)存的大小。先看一段代碼:
#include <stdio.h>
int main()
{
char str[] = "Hello";
char *p = str;
int n = 10;
int a = sizeof(str);
int b = sizeof(p);
int c = sizeof(n);
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", c);
return 0;
}
你能正確說出這段代碼的執(zhí)行結(jié)果嗎缔莲?如下圖:
讓很多人比較疑惑的是變量b的值為什么是4哥纫。如果你仔細看了之前的文章,那么肯定知道它表示的是指針變量在內(nèi)存中的大小痴奏。
3. strcpy函數(shù)實現(xiàn)
接下來蛀骇,我們通過這個函數(shù)的實現(xiàn)來介紹幾個筆試中常見的問題。
char* strcpy(char* strDest, const char* strSrc);
3.1. 不調(diào)用C語言庫函數(shù)读拆,編寫strcpy函數(shù)
在我的印象中擅憔,遇到過很多次這樣的題目。難度稍高一些的嵌入式開發(fā)題目要求用效率最高的方式實現(xiàn)檐晕。正確代碼如下:
char* strcpy(char* strDest, const char* strSrc)
{
assert((strDest != NULL) && (strSrc != NULL));
char* address = strDest;
while ((*strDest++ = *strSrc++) != '\0')
NULL;
return address;
}
這種寫法應(yīng)該已經(jīng)非常接近庫函數(shù)的實現(xiàn)方法了暑诸,它的效率非常高。
3.2. strcpy能夠把strSrc的內(nèi)容復(fù)制給strDest辟灰,為什么需要char*類型的返回值个榕?
這個問題其實沒有唯一答案,你可以談自己對程序設(shè)計的理解芥喇,并給出一個你覺得合適的答案西采。這里給出一個大多數(shù)面試官比較喜歡的答案:
這樣設(shè)計能夠?qū)崿F(xiàn)鏈式表達式,如:
int len = strlen(strcpy(strDest, "ABCDE"));
3.3. const char* strSrc中const的意義继控?
其實const這個關(guān)鍵字嚴格意義上說是C++中的械馆,但越來越多的C語言代碼開始使用這個關(guān)鍵字胖眷。它的意義是保證strSrc這個字符串的內(nèi)容不會被strcpy修改。
今天就先到這里霹崎,有什么問題歡迎郵件溝通瘦材。
我是天花板,讓我們一起在軟件開發(fā)中自我迭代仿畸。
如有任何問題食棕,歡迎與我聯(lián)系。