(投稿を読む前にこの段落を読んでください。私はこの投稿を読むことに興味がある人は注意深く読んでみてください、そしてもちろん、完全に理解するまで反対しないでください、ありがとう。)
現在はコミュニティウィキになっているため、誰かがいずれかの概念に同意しない場合は、何が間違っているのか、その理由を明確かつ詳細に説明して修正してください。可能であれば、出典を明記するか、再現可能な証拠を提供してください。
回答
NULL == 0の根本的な要因となる可能性がある他のいくつかの理由を次に示します
- ゼロが偽であるため、の
if(!my_ptr)
代わりに直接実行できますif(my_ptr==NULL)
。
- 開始されていないグローバル整数はデフォルトですべてゼロに初期化されるため、すべてゼロのポインターは初期化されていないと見なされます。
ここで私は他の答えについて一言述べたいと思います
構文糖のためではない
構文上の砂糖のためにNULLがゼロであると言ってもあまり意味がありません。もしそうなら、配列の長さを保持するために配列のインデックス0を使用しないのはなぜですか?
実際、Cは内部実装に最もよく似た言語ですが、構文上の砂糖のためにCがゼロを選択したと言っても意味がありませんか?他の多くの言語で行われているように、ゼロをNULLにマッピングするのではなく、キーワードnullを提供します。
そのため、今日の時点では構文上の砂糖にすぎないかもしれませんが、C言語の開発者の本来の意図は構文上の砂糖ではなかったことは明らかです。
1)仕様
しかし、C仕様では定数0からヌルポインター(セクション6.3.2.3)を示し、実装定義としてNULLを定義している(C11仕様のセクション7.19、およびC99仕様の7.17)ことは事実ですが、 Cの発明者によって書かれた本「Cプログラミング言語」では、5.4節で次のように述べられています。
Cは、ゼロがデータの有効なアドレスになることは決してないことを保証します。したがって、ゼロの戻り値を使用して、異常なイベント(この場合はスペースなし)を通知できます。
ポインターと整数は交換できません。ゼロは唯一の例外です。定数ゼロはポインターに割り当てられ、ポインターは定数ゼロと比較されます。記号定数NULLは、これがポインターの特殊な値であることをより明確に示すニーモニックとして、ゼロの代わりによく使用されます。NULLはで定義されています。以降ではNULLを使用します。
(「ゼロアドレス」という言葉から)わかるように、少なくともCの作成者の当初の意図はアドレス0であり、定数ゼロではありませんでした。さらに、この抜粋から、仕様が定数ゼロは、おそらくゼロと評価される式を除外するのではなく、代わりに整数定数ゼロを含めて、キャストなしでポインターコンテキストで使用できる唯一の整数定数にします。
2)まとめ
仕様では、ゼロアドレスはゼロ定数とは異なるものとして扱うことができると明記されていませんが、そうではありません。また、ヌルポインター定数を処理するとき、実装として定義されているとは主張していません。NULLで行います定義された定数、代わりにゼロ定数及びゼロアドレスとの間の差があるかもしれないこと、それがゼロであることを示すことを特徴。
(ただし、これが当てはまる場合は、なぜNULLが実装定義されているのか不思議に思います。そのような場合、コンパイラはとにかくすべての定数を実際の実装定義NULLに変換する必要があるため、NULLも定数ゼロになる可能性があるからです。)
ただし、実際のアクションではこれは見られません。一般的なプラットフォームでは、アドレス0と定数0は同じように扱われ、同じエラーメッセージをスローします。
さらに、今日のオペレーティングシステムは、CのNULLポインターによるゼロアドレスへのアクセスを防ぐために、実際には最初のページ全体(範囲0x0000から0xFFFF)を予約しているという事実もあります(http://en.wikipedia.org/wiki/を参照)。 Zero_page、および「Jeffrey RichterおよびChristophe NasarreによるC / C ++を介したWindows(Microsoft Press発行)」)。
したがって、私は実際にそれを実際に見たと主張している人から、プラットフォームとコンパイラ、そして彼が実際に行った正確なコードを指定してください(ただし、仕様での曖昧な定義に起因しますが、プラットフォームは彼がやりたいことは何でも自由にできます)。
しかし、どうやらCの作者はこれを念頭に置いておらず、「ゼロアドレス」について話していたようです。また、「Cはそれが有効なアドレスではないことを保証します」、および「NULLは単なるニーモニック」は、本来の意図が「構文上の砂糖」ではなかったことを明確に示しています。
オペレーティングシステムのせいではない
また、いくつかの理由により、オペレーティングシステムがアドレス0へのアクセスを拒否すると主張しています。
1)Cが書かれたとき、このWikiページhttp://en.wikipedia.org/wiki/Zero_pageで確認できるように、そのような制限はありませんでした。。
2)事実は、Cコンパイラがメモリアドレス0にアクセスしたことです。
これは、BellLabsによる次の論文(http://www.cs.bell-labs.com/who/dmr/primevalC.html)からの事実であると思われます
2つのコンパイラは、これに対する対処方法の詳細が異なります。前の例では、関数の名前を付けることで開始点が見つかりました。後者では、開始は単に0であると見なされます。これは、最初のコンパイラがメモリマッピングを備えたマシンが作成される前に作成されたことを示します。そのため、プログラムの起点は位置0ではなく、2番目の時点ではマッピングを提供するPDP-11がありました。
(実際、今日(ウィキペディアとマイクロソフトプレスから上記の参照を引用したように)、ゼロアドレスへのアクセスを制限する理由は、CのNULLポインターが原因です!したがって、結局は逆になります!)
3)CはオペレーティングシステムやCコンパイラの記述にも使用されていることを忘れないでください。
実際、CはUNIXオペレーティングシステムを作成する目的で開発されたため、アドレスCを制限する理由にはならないようです。
(ハードウェア)コンピューターが(物理的に)アドレス0にアクセスする方法の説明
ここでもう1つ説明したい点がありますが、どのようにしてアドレス0を参照することができるのでしょうか。
少し考えてみてください。アドレスはプロセッサによってフェッチされ、メモリバス上で電圧として送信されます。これは、メモリシステムによって実際のアドレスに到達するために使用されますが、ゼロのアドレスは電圧がないことを意味しますでは、メモリシステムの物理ハードウェアはアドレス0にどのようにアクセスするのでしょうか。
答えは、アドレス0がデフォルトであること、つまり、メモリバスが完全にオフの場合、メモリシステムは常にアドレス0にアクセスできるため、実際のアドレスを指定せずに読み取りまたは書き込みを要求する(これはアドレス0の場合)は自動的にアドレス0にアクセスします。
if (p != 0)
するif (p)
こともできますが、Javaを使用する場合は習慣から抜け出す必要があります。