C++捉蟲筆記

《捉蟲歷險記—C++ bug大圍剿》讀書筆記

1.       你會用C++寫正確Hello World 程序嗎?

你認爲你能嗎?我寫了一年多的程序,最初我認爲我是可以的,但是當我看到錯誤的程序的時候,我卻沒發現那是個錯誤,原因只有一個,我對C++的函數的瞭解太膚淺了。

示例程序如下:

#include <iostream>

 

void main(void)

{

std::cout<<"Hello World/n";

}

你認爲上面的程序是對的嗎?至少我把它卸載IDE中,編譯運行的時候,出現了正確的的輸出結果,所以我認爲是對的,其實不然。

原因:函數main()不是一個void型函數,而是一個int型函數。

正確的程序如下:

#include <iostream>

 

int main()

{

std::cout<<"Hello World/n";

return (0);

}

2.       靜態變量和自動變量的區別

靜態變量的生存期就是整個程序的運行期。在程序開始運行前就爲其分配相應的存儲空間,在程序的整個運行期間一直佔用,直到結束。

自動變量的生存期是說明了自動變量的函數或分程序。它對存儲空間的利用是動態的。其初值在每次爲自動變量分配存儲後都要重新設置。

示例程序:

#include <stdio.h>

 

//first--Demonstration of automatic variable.

int first(void)

{

int i = 0;  //Demonstration variable

return (++i);

}

 

//second--Demonstration of static variable

int second(void)

{

static int i = 0; //Demonstration variable

return (++i);

}

 

int main()

{

int counter;     //Call counter

 

for(counter=0; counter<3; counter++)

{

        printf("First %d/n",first());

}

 

for(counter=0; counter<3; counter++)

{

        printf("Second %d/n",second());

}

return (0);

}

結果輸出:

3.       return (++i) return (i++)

return (i++)

(1) 保存i的值

(2) 遞增i

(3) 返回已保存的值

return (++i)

(1) 遞增i

(2) 保存i的值

(3) 返回保存的值

4.       典型的初始化問題

 

#include <iostream>

int main()

{

int sum;   //the running sum

int count; //the current number

for(count=1; count<=100; count++)

{

        sum += count;

}

 

std::cout<<"The sum of numbers"<<"between 1 and 100 is "<<sum<<'/n';

return (0);

}

 你認爲上面的程序輸出會是你想要的結果嗎?也許吧,但機會太小了,由於初始化過程中對變量sum 沒有做初始化,因此您不能指望沒有初始化的變量,它可能包含任何值,所以輸出結果也就可能是任何的值,正確的做法就是int sum = 0;

5.       行結束符對程序的影響

#include <iostream>

int main()

{

int result; //result of the addition

result = 2 + 2;

std::cout<<"the answer is "<<result;

std::cout<<"the answer is "<<result<<'/n';    //建議的寫法

return (0);

}

作者對程序給出了這樣的解釋

MS-DOS中,您會得到如下結果:

The answer is 4C:>#

(#是光標)

UNIX系統中,您可能得到如下結果:

The answer is 4$ #

問題在程序員沒有在std::cout語句的結束處加上行結束標誌。結果就是:程序運行,輸出一個語句,然後退出,而讓光標停留在輸出行的末尾位置。命令行處理器接着就繼續運行,並在程序的輸出內容之後輸出其系統命令提示符(MS-DOSC:>UNIX$)

但我在自己機器上的執行並沒有出現這樣的結果,C:>始終也沒有出現,我想惟一的解釋就是後來的C++IDE做了改進 當你的輸出結尾沒有行結束符的時候自動加上。

6.       第一個內存泄露問題

這是我第一次接觸到內存泄露的問題,以前只知道有這麼回事,而且程序最要命的錯誤就是內存泄露,調試起來會很費勁,今天也算是初見端倪,看來以後真的防着這個傢伙了,哈哈。

程序是這樣的,輸出1—5之間數字的平方僅此而已,看看下面的程序,是否滿足你的要求呢?

#include <iostream>

int main()

{

int array[5];    //an array for the squares

int i; //index into the array

for(i=1; i<=5; i++)

{

        array[i] = i * i;

}

for(i=1; i<=5; i++)

{

        std::cout<<i<<" squared is "<<array[i]<<'/n';

}

return (0);

}

程序結果輸出正確,但是會報要命的系統錯誤,如下圖示:

其實原因很簡單:

C++數值下標的基值是0。因此,數組array[5]的有效元素是:

array[0], array[1], array[2], array[3], array[4]

然而,程序員使用的元素是1-5。不存在元素array[5],因此,程序就修改了隨機內存,導致內存泄漏。

這也是爲什麼C++程序不使用這樣語句的原因:

for (i = 1; i <= 5; ++i) {

而是使用:

for (i = 0; i < 5; ++i) {

修改後的程序如下:

#include <iostream>

int main()

{

int array[5];    //an array for the squares

int i; //index into the array

for(i=0; i<5; i++)

{

        array[i] = (i+1) * (i+1);

}

for(i=0; i<5; i++)

{

        std::cout<<i+1<<" squared is "<<array[i]<<'/n';

}

return (0);

}

7.       用字符變量表示數字的時候要多加小心。它們可能達不到您想要的結果。

比如如下程序,你認爲輸出是什麼呢?

#include <iostream>

int main()

{

char ch;  //the flag

ch = 0xFF;     //set the flag

 

//check the flag

if(ch == 0xFF)

{

        std::cout<<"Sucessed/n";

}

else

{

        std::cout<<"Fails/n";

}

return (0);

}

或許你認爲肯定是Sucessed,但輸出的缺失Fails,原因是這樣的:ch可能是一個有符號的字符。這意味着,如果ch0xFF,則當它爲了比較而轉換爲有符號整數的時候,您會得到int(ch)=-1(0xFFFFFFF)。這不是0xFF,導致比較失敗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章