2

質問をする前に、「エキスパート C プログラミング」[ページ:276、最後の段落] を引用したいと思います。

「Illiffe ベクトル データ構造体の優れた点は、文字列へのポインターの任意の配列を関数に渡すことができることですが、ポインターの配列のみ、および文字列へのポインターのみを渡すことができます。これは、文字列とポインターの両方に明示的な out の規則があるためです。 -エンド マーカーとして使用できる境界値 (それぞれ NUL およびNULL )。"

したがって、上記のテキストから私が理解したのは、ポインターの配列がある場合、それらは NULL のような明示的な範囲外の値を持つということです。(私が間違っている場合は訂正してください...)

そのため、ポインターの配列のデフォルト値は何なのか疑問に思いました(ポインターの配列の最後のポインターはNULLになると考えていました)。以下のコード スニペットを試してみましたが、結果は大きく異なりました。

    int *x[2];
    printf("%p %p",x[0],x[1]);

出力は次のとおりです: (nil) 0x400410

    int *x[3];
    printf("%p %p %p",x[0],x[1],x[2]);

出力: 0xf0b2ff 0x400680 (なし)

    int *x[4];
    printf("%p %p %p %p", x[0],x[1],x[2],x[3]);

出力は次のとおりです: (nil) 0x4003db 0x7fffe48e4776 0x4006c5

したがって、上記の出力では、明示的な境界外 (nil) 値がポインターの 1 つ (1 つのポインターは NIL) に割り当てられていることは明らかですが、それは本当にエンドマーカーですか? いいえ。

C言語の「実装定義」の1つですか?

Ubuntu マシンで GCC コンパイラ (4.6.3) を使用しています。

4

5 に答える 5

4

C言語の「実装定義」の1つですか?

いいえ、それは実装定義ではありません。単純な「未定義」です。同じことがすべてのタイプの配列に当てはまります。それらに表示される値は、明示的に初期化されるまで未定義です。

上記のテキストから私が理解したのは、ポインターの配列がある場合、それらは のような明示的な範囲外の値を持つということNULLです。

NULL著者は、ポインターの配列に「値なし」をマークするために使用できる値 (具体的には値) があると言いたかったのです。作成者は、そのような値のないマーカーがデフォルトでポインターの配列に配置されることを暗示するつもりはありませんでした。

于 2013-09-12T19:34:02.180 に答える
1

C では、ローカル変数に「デフォルト」値を設定する必要はありません。そのため、コンパイラが 2 つ (または 3 つ) のメモリ ロケーションを予約する場合、初期値はこれらのメモリ ロケーションが以前に含まれていたものであり、デフォルトの初期化は行われません。

于 2013-09-12T19:33:46.280 に答える
0

配列がファイル スコープ (関数の外) またはstaticキーワードで宣言されていない限り、配列の内容は初期化されません。各要素には、有効なアドレスに対応する場合と対応しない場合があるランダムなビット パターンが含まれます。

配列がファイル スコープまたはstaticキーワードを使用して宣言されている場合、各要素は暗黙的に に初期化されNULLます。NULL ポインターを逆参照しようとすると、未定義の動作が発生することに注意してください。そのため、何かを行う前に、ポインターが NULL でないことを確認する必要があります。

null ポインタは、明確に定義された「どこにもない」ことを表し、有効なメモリ アドレスと等しくないことが保証されています。NULL ポインター定数1と NULL ポインター2があり、この 2 つは必ずしも同じではないことに注意してください。ソース コードでは、マクロNULLは null ポインター定数に設定されています。変換中、ソース コード内の が出現するたびNULLに、実際のヌル ポインター値に置き換えられます。

NULL 以外の無効なポインター値があります。NULL が明確に定義されており、どこでも同じように機能するだけです。


1. ポインター コンテキストで使用される 0 値の整数式。裸0の 、 または(void *) 0、または 0 に評価されるその他の何か
である可能性があります。

于 2013-09-12T19:52:51.807 に答える