0x0の場所を指すポインターとNULLに設定されるポインターの違いは何ですか?


12

0x0000を指すポインターは、NULLに設定されたポインターと同じですか?NULL値がC言語で定義されている場合、物理的にどの位置に変換されますか?0x0000と同じですか?これらの概念に関する詳細はどこで入手できますか?


1
これは、すでにスタックオーバーフローに頼まれました- stackoverflow.com/questions/1296843/...を。私たちにとっては境界線だと思いますが、今のところは疑いの恩恵を与えたいと思っています。
ChrisF

回答:


12

ここでの答えのほとんどが、少なくとも明示的には対処されていない点は、nullポインターは実行中に存在する値であり、nullポインター定数はCソースコードに存在する構文構造です。

ヌルポインタ定数は Karlsonの答えは正しく述べているように、いずれかの値が0(シンプルが持つ整数定数式で0最も一般的な例である)、またはこのような表現キャストvoid*(など(void*)0)。

NULLはマクロで定義され<stddef.h>、他のいくつかの標準ヘッダーで定義され、実装定義のNULLポインター定数に展開されます。展開は通常、0または((void*)0)(他の言語規則を満たすために外側の括弧が必要です)のいずれかです。

そのため、リテラルは0、ポインタ型の式を必要とするコンテキストで使用される場合、常に a null pointerに評価されます。つまり、オブジェクトを指さない一意のポインタ値です。それはnullポインタの表現について何も意味しませ。ヌルポインターは、一般にすべてビット0として表されますが、何でも表すことができます。しかし、nullポインターがとして表される場合、またはnullポインター定数である場合でも。0xDEADBEEF0(void*)0

stackoverflowの質問に対するこの回答これをうまくカバーしています。

これは、とりわけ、メモリの領域をall-bits-zeroに設定できるmemset()orがcalloc()、その領域のポインタを必ずしもnullポインタに設定しないことを意味します。彼らはほとんどの実装でそうするでしょうが、言語はそれを保証しません。

この質問は、の重複と見なされていない理由を私は知らないこの1、またはそれはここで話題ですか。


1
Cの設計と進化についての私の主張の1つは、ゼロの数字が非推奨のヌルポインターの表現として引き続き使用されていることです。言語の初期(たとえば、関数プロトタイプのようなものが出現する前)では、ポインターと整数は十分に互換性があったため、NULLポインターに「0」を使用するのは簡単で、「機能する」だけでした。ただし、整数量のゼロとNULLポインターを区別する必要が生じた場合、キーワードまたは演算子のシーケンスを優先して、「0」表現を非推奨にする必要がありました。
-supercat

これは、プラットフォームに応じてNULLが割り当てられたときに、NULLポインターが実際に特定の場所を指すことがあるということですか?ヌルポインター定数は構文構造かもしれませんが、コードを実行するとどうなりますか?この構文構造がGNU / Linuxプラットフォームでコンパイルされたと仮定しましょう。NULLを割り当てるときのポインター値は何ですか?この住所は他の住所とどのように異なりますか?
アーピス

1
@Arpith:ポインターオブジェクトへの割り当てNULL、またはNULLポインター定数は、そのオブジェクトの値をNULLポインターに設定します。マシンレベルでは、有効なメモリチャンクを指している可能性があります。NULLポインターの逆参照には未定義の動作があります。アドレスでメモリのチャンクにアクセスすること0x0000000は、文字通り他のものと同様に有効な動作です。このアドレスは、(a)と等しいことを比較しNULL、(b)Cオブジェクトへのポインターと等しくないことを比較することにより、他のアドレスとは異なります。NULLポインターは、何も指し示していないことを示すために使用される任意のポインター値です。
キーストンプソン

1
マシンレベルでは、有効なメモリチャンクを指す場合がありますが、ほとんどの C環境では無効なメモリを指すため、ポインタを使用しようとするとハードウェアトラップ/フォールト/例外が発生します。通常は、非常に単純なハードウェアプラットフォーム(メモリ管理をサポートしていないプラットフォーム)でのみ使用されます。NULLポインタが有効なメモリの場所を指します。
ソロモンスロー

7

そこにあるすべてのプラットフォームは、必要に応じてNULLを自由に定義できます。

C標準によると、ポインターにゼロを割り当てると、その値はNULL値に変換されます(そのプラットフォームの場合)。ただし、NULLポインターを取得してintにキャストすると、ゼロになるという保証はありません。そこにあるすべてのプラットフォームで。ただし、ほとんどのプラットフォームではゼロになります。

C言語仕様で見つけることができるものに関する情報。1つのソース、私が保証できない信頼性は、これです:http : //www.winapi.co.kr/pds/doc/ISO-C-FDIS.1999-04.pdf


2
彼らが標準から脱却することを選ぶなら、彼らは自由に再定義しNULL pointer constantます。私の知る限り、それを行うコンパイラはありません。
カールソン

NULLを0として実装していないコンパイラはありますか?また、NULLはfalseと評価されることが保証されていますか?
ウゴレン

NULLは、標準でfalseと評価されることが保証されています。NULLを0として実装していないコンパイラ(実際にはプラットフォーム)があるかどうかはわかりません。真剣にそれを疑いますが、標準では禁止されていません。
マイクナキス

プラットフォームメーカー喜ばとの定義としてであってよいメモリ内の抽象「ヌルポインタ定数」(スペックで述べたように)、の表現との間の混乱があるNULLように展開しなければならないマクロ、0C ++でのいずれか0または(void *)0Cには、それは本当の「ヌルポインタ定数」だからです。
Jan Hudec

NULLは理論的には何でも定義できますが、標準では、ポインターに型キャストされた値0を持つint定数がNULLポインターになるという保証があります(ISO 9899:1999 6.3.2.3/3)。stddef.hのNULLマクロはNULLポインター(7.17 / 3)でなければならないため、0または(void *)0のいずれかとしてNULLを実装しないとコンパイラーにとって非常に負担になります。

1

これは、C言語で定義されています。これは、同一の不変のマシンアドレスがないためです。もしそうなら、それから抽象化する必要はありません!ほとんどのプラットフォームでは、最終的にNULLが何らかのタイプの0として実装される可能性がありますが、移植性にまったく関心がある場合、これが普遍的であると仮定するのは間違っています。



0

C標準文書セクションによると6.3.2.3

値0の整数定数式、またはそのようなvoid *型にキャストされる式は、nullポインター定数と呼ばれます。55)nullポインター定数がポインター型に変換される場合、結果のポインターはnullポインターと呼ばれます任意のオブジェクトまたは関数へのポインターと等しくない比較を保証します。

これまでのところ、これから脱却したコンパイラは見たことがありません。


@PéterTörökあなたは正しいです、それはタイプミスです。:)
カールソン

1
はい。ただし、実際には0の数値を持つポインターについては何も言わないことに注意してください。ほとんどのプラットフォームではそうではありません。
Jan Hudec
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.