2012-06-17 76 views
3

我想用C++來做我的第一個嬰兒步驟。請解釋:在for循環之後跳過了一行?

有人可以解釋爲什麼這不工作,我期望的方式嗎?

#include <iostream> 
#include <stdio.h> 

using namespace std; 

int main (int argc, char *argv[]) { 
    int i; 
    printf("[D] sizeof argv is: %d\n", sizeof(argv)); 
    printf("[D] sizeof int is: %d\n", sizeof(int)); 
    printf(
     "[D] sizeof argv/sizeof int is: %d\n", 
     sizeof(argv)/sizeof(int) 
    ); 

    for (i = 0; i < (sizeof(argv)/sizeof(int)); i++) { 
     printf("[D] i is: %d\n", i); 
     cout << argv[i] << endl; 
    } 

    if (cout.fail()) { 
     printf("cout failed!\n"); 
    } 

    cout << "Hello world" << endl; 
} 

現在測試:

[email protected]:~/sandbox/tuts$ g++ string02-d.cpp 
[email protected]:~/sandbox/tuts$ ./a.out hello world 
[D] sizeof argv is: 8 
[D] sizeof int is: 4 
[D] sizeof argv/sizeof int is: 2 
[D] i is: 0 
./a.out 
[D] i is: 1 
hello 
Hello world 
[email protected]:~/sandbox/tuts$ ./a.out 
[D] sizeof argv is: 8 
[D] sizeof int is: 4 
[D] sizeof argv/sizeof int is: 2 
[D] i is: 0 
./a.out 
[D] i is: 1 
cout failed! 
[email protected]:~/sandbox/tuts$ echo $? 
0 
[email protected]:~/sandbox/tuts$ 

爲什麼當只有一個argv中的項目(的argv [0],是 「./a.out」),在 「世界,你好」 被跳過?不管argc還是argv,我都找不到任何理由,爲什麼會跳過這個選項!

的OS是在64位(這樣sizeof(int) == 4)的Debian擠壓。

更新:刪除#包括噪音,增加了一些調試。

更新2:增加了一些基於user315052的答案的調試。 (現在表明他是對的。)

+2

它應該是'for(i = 0; i Griwes

+3

順便說一下,這不是** C++ **,甚至不是** C++ **中的有效函數聲明!它應該是'int main ...' –

+2

您不使用''或''。在C++程序中,當您需要C''頭部的服務時,您應該使用''。 –

回答

3

編輯:,因爲不確定的行爲被調用時,任何事情都有可能發生。調整答案。

「Hello World」可能不會被跳過。實現您的for循環是不正確的。它可能沒有出現的一個原因是你已經打印了一些掩蓋了信息外觀的東西。爲了測試這一點,將輸出重定向到將顯示輸出流的二進制內容的東西。

./a.out | xxd 

另一原因可能是,該輸出被阻止,因爲std::cout遭受故障從企圖打印NULL指針爲字符串。要測試這一點,請在循環中的打印語句後檢查std::cout.fail(),如果遇到此消息,請將消息指向std::err。如Boann所示,程序也可能崩潰。但是,操作系統會提供這種效果的診斷,並且您沒有報告這種行爲。

對於那些函數參數陣列,該編譯器將它們作爲一個指針。這是一種從C繼承的行爲,其中通過允許數組的名稱衰減到其第一個元素的地址(除了少數例外,其中一個是sizeof),通過「引用」傳遞數組。因此,使用sizeof來確定argv中元素的數量將不起作用。 C和C++都提供了兩種方法來確定何時到達argv向量的末尾。一個是argc這是參數計數。第二個是argv的最後一個元素必須是NULL指針。

下一次你有一個真正的數組,你可以使用下面的計算元素的數量與sizeof

SomeThing array[] = { /* ... things ... */ }; 
size_t array_size = sizeof(array)/sizeof(array[0]); 

這樣,如果SomeThing變化,數組的大小仍然是正確計算。

+0

或者,更好的是'./a.out | hd'。 – Griwes

+0

'xxd'和'hd'沒有在任何地方顯示「Hello world」:// –

+0

@Griwes:感謝您的輸入,我的系統沒有'hd',但我確實認爲管道更好。編輯。問候 – jxh

0

我無法重現您的錯誤。在這兩種情況下,我都會打印「Hello World」。

[email protected]:~/Dev/ScratchDir$ ./a.out 
./a.out 
Hello world 
[email protected]:~/Dev/ScratchDir$ ./a.out Hello 
./a.out 
Hello world 
[email protected]:~/Dev/ScratchDir$ 

你可以檢查是否有任何核心轉儲可能嗎?

+0

沒有核心轉儲,'$?'爲零。 –

+0

好吧,可能是因爲它打印了一些廢棄的文件,而這些文件正在退出您的Hello World。你可以做'./a.out | hd' like @Griwes says – kjp

+3

「我無法重現你的錯誤。」 kjp遇到未定義的行爲,未定義的行爲符合kjp。 –

5

您的sizeof檢查有問題,始終評估爲2 [在64位上]。因此,如果您不給程序至少一個參數,它會嘗試從未映射的內存中打印argv[1],並崩潰。