3

私は C++ で最初の赤ちゃんのステップを実行しようとしています。

なぜこれが期待どおりに機能しないのか、誰か説明できますか?

#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;
}

今テスト:

aloism@azzgoat:~/sandbox/tuts$ g++ string02-d.cpp
aloism@azzgoat:~/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
aloism@azzgoat:~/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!
aloism@azzgoat:~/sandbox/tuts$ echo $?
0
aloism@azzgoat:~/sandbox/tuts$

argv に項目が 1 つしかない場合 (argv[0]、"./a.out")、"Hello world" がスキップされるのはなぜですか? argc または argv に関係なく、これがスキップされる理由がまったく見つかりません!

OSは64ビットのDebian Squeezeです(そうsizeof(int) == 4です)。

更新: #include ノイズを削除し、デバッグを追加しました。

更新 2: user315052 の回答に基づいてデバッグを追加しました。(今では、彼が正しいことを示しています。)

4

3 に答える 3

5

sizeof チェックに問題があり、[64 ビットで] 常に 2 と評価されます。したがって、プログラムに少なくとも 1 つの引数を指定しないと、プログラムはマップされていないメモリから出力しようとしargv[1]、クラッシュします。

于 2012-06-17T15:38:25.707 に答える
3

編集:未定義の動作が呼び出されるため、何でも起こり得ます。答えを調整します。

「Hello World」はおそらくスキップされていません。あなたのforループが不適切であることを認識してください。表示されない理由の 1 つは、メッセージの外観を覆っている何かを印刷したことです。これをテストするには、出力ストリームのバイナリ コンテンツを明らかにするものに出力をリダイレクトします。

./a.out | xxd

別の理由として、ポインタを文字列として出力std::coutしようとして失敗したため、出力がブロックされている可能性があります。NULLこれをテストするにstd::cout.fail()は、ループ内の print ステートメントの後で確認し、メッセージstd::errが発生した場合はメッセージを送信します。

Boann が示すように、プログラムがクラッシュすることもあります。ただし、オペレーティング システムはその旨の診断を提供するはずであり、そのような動作は報告されていません。

関数パラメーターである配列の場合、コンパイラーはそれらをポインターとして扱います。これは C から継承された動作であり、配列の名前がその最初の要素のアドレスに減衰できるようにすることで、配列が「参照」によって渡されます (いくつかの例外はありますが、sizeofそのうちの 1 つです)。したがって、sizeof要素の数を決定するために使用しても機能しargvません。C と C++ はどちらも、argvベクトルの最後に達したときを判別する 2 つの方法を提供します。1 つはargc引数の数です。2 つ目は、 の最後の要素はポインターでargvなければならないということです。NULL

次回真の配列を取得するときはsizeof、次を使用して要素の数を計算できます。

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

このように、SomeThing変更された場合でも、配列サイズは適切に計算されます。

于 2012-06-17T15:39:06.737 に答える
0

エラーを再現できません。どちらの場合も「Hello World」が出力されます。

kjp@vbox:~/Dev/ScratchDir$ ./a.out 
./a.out
Hello world
kjp@vbox:~/Dev/ScratchDir$ ./a.out Hello
./a.out
Hello world
kjp@vbox:~/Dev/ScratchDir$ 

コアダンプがあるかどうかを確認できますか?

于 2012-06-17T15:33:11.783 に答える