- ベストアンサー
C言語のNULLについて
- C言語のNULLについて教えてください。
- NULLは、アドレスの0番地であり、参照先が無い(どこのメモリ箇所も指していない)と言う認識でいます。
- 実際は、メモリフォルトが起こらなかったです。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
NULL は、参照先が無い(どこのメモリ箇所も指していない)、と「見做す」という方が正しいでしょう。 > printf("[%p]\n", test); // 出力 [00000000] とあるように、実際に「0番地」を指しています。 // 環境によっては、0で無い場合もあります。 > memcpy(test, "123", 3); // メモリフォルト これは、「参照先が無い」ことが原因ではなく、その参照先に書き込み許可が無いことが原因です。 メモリ保護機能の無い小規模のマイコン等では、エラーにならないかもしれません。 > printf("[%s]\n", test); // 出力 [] これは、2通り考えられます。 (1) NULLの領域への読み出し権利があるため、その領域の「文字列」が表示されている。 0番地が0なら、空文字列ということになる (2)printf中で、 %s に対してNULLが指定されていたら、空文字を出力するように判定している if( str==NULL ) { puts("") } else { puts(str) } のようなイメージ GCC(で使われているglibc)のソースを眺めると、(2)のようです。
その他の回答 (4)
- notnot
- ベストアンサー率47% (4900/10358)
他の方のお書きの通り、*NULL へのアクセスは処理系依存です。 また、他の方のお書きの通り、ポインターに0を代入した場合に実際に何が代入されるかも処理系依存です。 処理系依存とは言っても、ちゃんとメモリ管理されいるOSであれば、セグメンテーションフォルト例外やページアクセス例外などのプログラム割り込みが起こって、プロセスが異常終了するのが普通です。 ということで、たまたまお使いの環境がOS無し、もしくは、簡易なOSであり、 >参照先が何かしらあったって事なのでしょうか? ということでしょう。 memcpy(test, "123", 4); printf("%s\n",test); でどうなりますかね。
お礼
ありがとうございます。
- 麻野 なぎ(@asano_nagi)
- ベストアンサー率35% (42/120)
NULLポインタについては、 http://www.kouno.jp/home/c_faq/c5.html#0 (C言語 FAQ 日本語訳 5章 ヌルポインター) に詳しいです。 実は、NULL は、「定数ゼロと比較したときに等しくなる」ことは規格で決められていますが、NULL が実際に0番地をポイントしているということは、決められていません。 なので、 char *test; test = NULL; としたときに、test が実際にどの番地を指していることは、「規格上不明」と言うことになります。 また、上述のことから、NULL が安全に比較できるのは(ポインタを除けば)定数ゼロだけです。 なので、手元のコンパイラで、 void func(void); int main() { char *p; int i; if(p == 0) func(); if(p == 1) func(); if(p == i) func(); return 0; } をコンパイルすると、 if(p == 1) func(); if(p == i) func(); は、「移植性のないポインタ変換」と警告が出たりします。
お礼
ありがとうございます。
- hanabutako
- ベストアンサー率54% (492/895)
メモリフォルトというのは聞いたことがありませんが、segmentation faultのことでしょうか。 libcの実装によってはprintfで文字列を出力するところでNULLを与えると、(null)などの文字列を表示するものがあります。 例えば、 http://svnweb.freebsd.org/base/head/lib/libc/stdio/vfprintf.c?revision=268930&view=markup 829 if ((wcp = GETARG(wchar_t *)) == NULL) 830 cp = "(null)"; ちなみに、この実装の場合、printf内部でvprintfが呼ばれ、その中でvfprintfが呼ばれています。
お礼
ありがとうございます。
- BuriBuri4
- ベストアンサー率28% (150/525)
この動作結果は処理系依存です。 0番地が物理メモリー上の何処を指しているのかコンパイルモデルによって変わります。 またプログラム/データ領域以外にアクセスした場合に何が起こるかはプロセッサとOSによって変わります。 Solaris系なら(多分) printf("[%s]\n", test); // 出力 [] の時点でアクセス違反でABENDします。
お礼
ありがとうございます。
お礼
とても分かりやすかったです、ありがとうございました。