1

これがプログラムです:

#include <stdio.h>

main() {
  int * i;
  int * j;
  printf("%d\n", i);
  printf("%d\n", j);
}

私はそれをコンパイルして実行しました、そして出力は次のとおりでした:

888086464
0

ただし、2番目のprintfをコメントアウトすると

#include <stdio.h>

main() {
  int * i;
  int * j;
  printf("%d\n", i);
  //printf("%d\n", j);
}

出力beomes:

0

なぜ2番目のprintfがポインタiを変更するのか疑問に思います。
そして、Cはどのようにポインターを初期化しますか?私の知る限り、ポインタが初期化されていない場合、その値はNullになります。これは0に等しいですよね?なぜ最初の出力でiが初期化されたのですか?

編集:皆さんからの提案に従って、私はいくつかの変更を加えました:

#include <stdio.h>

main() {
  int * i;
  int * j;
  printf("%p\n", i);
  printf("%p\n", j);
}

これは

0x7fff67a361b0
(nil)

しかし、2番目のprintfをコメントアウトすると

#include <stdio.h>

main() {
  int * i;
  int * j;
  printf("%p\n", i);
  //printf("%p\n", j);
}

出力はnilです。2つのprintfを含む最初のバージョンで、jだけがnilで、iはnilではないのはなぜか不思議です。

4

8 に答える 8

4

どちらのポインタも初期化しません。あなたが見ているのは未定義の振る舞いです。表示される値は、スタックからの単なるガベージ値であり、実行するたびに変更される可能性があります。

于 2013-03-12T16:22:46.523 に答える
3

ポインタを初期化していない場合は、任意の値をとることができます。

それらを初期化する必要があります。それ以外の場合は、を取得しundefined behaviorます。

また、ポインタを印刷する正しい方法は次のとおりです。

printf("%p", pointer);
于 2013-03-12T16:22:19.130 に答える
2

2つのバージョン用に生成されたマシンコードを確認することで、質問に答えることができます(gccの場合、これは-Sオプションである必要があります)。

2番目のバージョンでは、(どこでも使用されていないため)まったく作成されていないため、に使用されていたはずのスロットに作成されていると思われます。何らかの理由で、スタックは上位64ビットの後に続くように設定されていますjij0x00000000000000000x00007fff67a361b0

IOW、最初のバージョンでは、スタックは次のようになります

 Item        Address            00  01  02  03  04  05  06  07   
 ----        -------            --  --  --  --  --  --  --  --
    j        0x8000             00  00  00  00  00  00  00  00
    i        0x8008             00  00  7f  ff  67  a3  61  b0

一方、2番目のバージョンでは、次のようになります。

 Item        Address            00  01  02  03  04  05  06  07   
 ----        -------            --  --  --  --  --  --  --  --
    i        0x8000             00  00  00  00  00  00  00  00
             0x8008             ??  ??  ??  ??  ??  ??  ??  ??

(アドレス値は説明のみを目的としており、実際のアーキテクチャには対応していません)。

笑い声の場合は、printステートメントを次のように変更します

printf("%p: %p\n", &i, i);
printf("%p: %p\n", &j, j);

最初のバージョンでは

printf("%p: %p\n", &i, i);

第二に。&i2番目のバージョンで(変数のアドレス)に出力された値が、最初のバージョン (変数のアドレス)にi出力された値と同じになることを賭けます。&jj

-これはC言語とは関係がなく、特定の実装(コンパイラ、リンカなど)と関係があります。未定義の動作を呼び出しているとは思いませんが(これらの無効なポインターを介してメモリにアクセスしていない)、ポインター値を明示的に初期化しないという危険があります。

staticキーワードなしでブロックスコープで宣言された変数は初期化されません。変数がインスタンス化されたときにメモリにあるものはすべて初期値であり、そのビットパターンはそのタイプの有効な値を表していない可能性があります(これはトラップ表現と呼ばれます)。ファイルスコープ(関数の外部)またはstaticキーワードで宣言された変数は、スカラー型かポインター型かに応じて、0またはNULLに初期化されます。集合体タイプ(配列、構造体、および共用体)のルールは少し複雑ですが、基本的な原則は同じです。

于 2013-03-12T17:29:47.380 に答える
0

ポインタは何でも保持できます。Cは、指示がない限り、ローカル(自動)変数を初期化しません。それらを静的として定義すると、NULLで初期化されます。

また%p、ではなく、ポインタの印刷に使用する必要があります%d

于 2013-03-12T16:24:34.037 に答える
0

ポインタアドレスを初期化しないと、未定義の動作が発生します

ここでは、ポインタアドレスをintとして出力していますが、これは正しくありません。"%p" 代わりに使用する必要があります。"%d"

于 2013-03-12T16:25:04.487 に答える
0

「初期化されていません」は「初期化されて0」(またはNULL)とは大きく異なります。

変数ijは初期化されていません。彼らは記憶にあるものを残されています。

2番目をコメントアウトするとprintf、変数jは使用されなくなります。おそらくコンパイラによって最適化されています(まったく定義されていないことを意味します)。このような場合、iは別の場所にあり、初期化されていない値が異なる可能性があります。

これは実際には未定義の動作です。私の最後のセクションは純粋な憶測です、あなたは決して確信することができません。

于 2013-03-12T16:23:23.713 に答える
0

And, how does C initialize pointers?

Cはしません、あなたはそれをします。

As far as I know, if a pointer is not initialized, it would have value Null which is equal to 0, correct?

間違い。初期化されていない場合、定義された値はありません。ごみになります。初期化されていない変数を出力するとガベージが発生するため、出力を予測できません。

Why in the first output, the i was initialized?

そうではなく、たまたま0を指していました。

補足:%pポインタを印刷するときは、で印刷する必要があります。

于 2013-03-12T16:25:33.173 に答える
0

Cは自動的に初期化staticし、グローバル変数(グローバルは関数の外部で宣言されます)をゼロに設定するだけです。 自動変数(2つのポインターと呼ばれるもの)は自動的に初期化されないため、「スタックノイズ」(つまり、関数が初期化されたときにスタックにあった値が何であれ)を出力します。出力される値は実行ごとに変わる可能性があります。それらを初期化するNULL場合は、コンパイラに次のように指示する必要があります。

int *i = NULL;
int *j = NULL;
于 2013-03-12T16:26:36.363 に答える