- ベストアンサー
nullと""、\0とEOFの違いについて。
いつも気になっていたのですが、 (1)nullと""、(2)\0とEOFは、同じなのでしょうか、 違うのでしょうか。 (1)については、違う気がします。しかし、""は、 なにを表しているのか分かりません(0バイトなのか、 空文字にも文字コードがあるのか、""と空白" "は 違うのか)。 (2)は、同じだと思うのですが・・。 文字を数えたりすると、これらが気になります。 お願いします。
- みんなの回答 (14)
- 専門家の回答
質問者が選んだベストアンサー
意味が違ってくるんです。 (1) NULL と "" 同じ事です。NULLとは「未定、未知、不明」ですので まだ文字列が決まってない(設定しない)と言うことで 未定(=NULL)です。 (2)\0 と EOF こちらは違います。文字列の終端文字としての'\0'は NULLの事で、確定している文字が無くなった=文字列の終わり と判断しているのです。 EOFは文字列ではなくファイルの終端です。 処理系によって変わってきますが、Windowsでは NULL = 0 EOF = -1 と定義されてる事からも違うのは明らかです。
その他の回答 (13)
- ency
- ベストアンサー率39% (93/238)
ちなみに、これはおまけです。 '\0' と数値 0 は「同じもの」です。 C では、アスキーコードに対応する文字を取得する場合、'\<アスキーコード>' とすれば良いんです。 たとえば、 '\x41" '\101': 'A' と同じ '\x30" '\60': '0' (数字 0) と同じ # 「x」なしは 8進表記になるようです。 同様に '\x0" '\0' : 0 (数値 0 (全ビットが 0)) と同じ となります。 ですので、文字列の終端文字として、数値の 0 を使用しても、動作上はまったく問題はありません。 しかし、それでは数値 0 か終端文字かがわかりにくくなるため、終端文字として使用する場合は '\0' を使用するようにしましょう。 一応、ご参考まで。
- rentahero
- ベストアンサー率53% (182/342)
詳しい説明は#11の方のものを採用するに1票。 どうなっているかは、実験してみればよろしい。 #include <stdio.h> int main() { int i; printf("NULL = %x\n", NULL); printf("\"\" = %x\n", ""); printf("\"\"[0] = %x\n", ""[0]); printf("\"hoge\" = %x\n", "hoge"); for(i=0;i<=strlen("hoge"), i++) { printf("\"hoge\"[%d] = %x\n", i, "hoge"[i]); } printf("\\0 = %d\n", '\0'); printf("EOF = %d\n", EOF); return 0; } FreeBSDで実行したら、 > NULL = 0 > "" = 804857e > ""[0] = 0 > "hoge" = 8048594 > "hoge"[0] = 68 > "hoge"[1] = 6f > "hoge"[2] = 67 > "hoge"[3] = 65 > "hoge"[4] = 0 > \0 = 0 > EOF = -1 となりました。 したがって。 NULLは特別なポインタ(0)として定義されている。 ""はdataエリアに定義される。(section .rodata) 1バイト目に'\0'が入っている。 "hoge"は""の後のdataエリアに定義される。 1バイト目から'h', 'o', 'g', 'e', '\0'の順に入っている。 '\0'そのものは0。 EOFは-1。 とそれぞれなっていることがわかります。 参考までに、EOFの定義がどうなってるかを調べてみると、 > grep EOF /usr/include/stdio.h #define __SEOF 0x0020 /* found EOF */ #define EOF (-1) #define SEEK_END 2 /* set file offset to EOF plus offset */ #define __sfeof(p) (((p)->_flags & __SEOF) != 0) #define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF))) となっており、確かに(-1)と定義されていることが、 同様にNULLについても調べてみると > grep NULL /usr/include/stdio.h #ifndef NULL #define NULL 0 * _ub._base!=NULL) and _up and _ur save the current values of _p and _r. struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ となっており、確かに0と定義されていることがそれぞれわかります。
- ency
- ベストアンサー率39% (93/238)
(1) null と "" について ⇒違います。 # null ではなく NULL ですよね? NULLは「ヌルポインタ (NULL Pointer)」のことです。 これは、そのポインタがどこも指していないことを保障する値です。 実装上は、 #define NULL 0 または #define NULL (void*)0 となっていると思いますが、0番地がどこも指していないアドレスとして使われている・・・というわけでもありません。 ポインタ型の変数に「0」が設定されていたら、コンパイラがそれをヌルポインタとして読み替えているだけです。 また、"" は空文字列、すなわち0バイトの文字列です。 文字列の終端文字として '\0' が使用されるため、値としては '\0' 一文字がその文字列の領域に入っていることになります。 "hoge" -> 'h' 'o' 'g' 'e' '\0' "" -> '\0' (2) \0 と EOF ⇒違います。 '\0' は「ヌル文字 (NUL Character)」といい、アスキーコードの 0x00 (NUL) に相当します。 C では、文字列の終端文字として使用される値です。 EOF はファイルの終端にある値で #define EOF (-1) と定義されていると思います。 ------------------------------------------------ 以下、参考・・・ ------------------------------------------------ getc()、getchar() 等、ファイルや標準入力から文字を読み込んで、その文字を返す関数 (or マクロ) では、「これ以上文字はないよ」ということを表すために EOF が返されます。 文字 (1byte) が 0x00~0xFF までありますが、戻り値の型が int型になっているので、EOF (-1) とすべての文字を区別することができます。 # そもそも、C には「汎整数拡張」という妙な (?) 規則があって、 # int型より小さな型は、int型に格上げされてしまいます。 また、gets()、fgets() といった文字列 (の先頭要素へのポインタ) を返す関数では、読込み完了を表すのに NULL (ヌルポインタ) が使われます。 これは、戻り値が char型へのポインタなので、最後にどこも指していないポインタ = NULL (ヌルポインタ) を返しているわけです。
- hpsk
- ベストアンサー率40% (48/119)
みなさんがいろんな回答をされていて混乱していると思いますので、 とりあえず参考URLの5章と12.1あたりを読んでみてください。 ヌルに関しては、この言葉がいろんな意味に使われていることが質問/回答者の混乱の元になっていると思います。 ・ヌル文字:文字列の終端を表す文字('\0') ・ヌルストリング:長さゼロの文字列("") ・ヌルポインタ:何もさしていないポインタ(ヘッダで#defineされているNULLはこれ)
- tikisukeman2
- ベストアンサー率32% (32/99)
他の人の回答を読みました。残念ながら大体の人があまり性格には理解されていないみていですね・・・・。 C,C++の、文字列は、メモリ上では、文字コード列で表されています。で、C,C++の変数char*などを使ってその文字コード列の先頭のメモリアドレスを保持します。で、どこまでが文字列なのかわからなくなるといけないので最後の文字列の次の一バイトに'\0'というしるしを入れるのです。 たとえば、 char* pHoge = "abcde" ; は、5文字ですがメモリ上のeの次のアドレスには '\0'が入っていますので、pHogeは全部で6byteの領域を保持していることになります。
- tikisukeman2
- ベストアンサー率32% (32/99)
(1) 違う ""は終端文字をあらわす。 つまり、メモリサイズ 1byteで中に'\0'が入っている。 NULL は、メモリ領域そのものが無い。 "" 終端文字列のみ、文字列長0、メモリ1byte " " スペース+終端文字、文字列長1、メモリ2byte (2) 違う Windows MS-DOSでは 1Ah EOFはファイルの終端を表す。OSによって違う。 EOF は End of File です。念のため。
- tikisukeman2
- ベストアンサー率32% (32/99)
(1) 違う ""は終端文字をあらわす。 つまり、メモリサイズ 1byteで中に'\0'が入っている。 NULL は、メモリ領域そのものが無い。 "" 終端文字列のみ、文字列長0、メモリ1byte " " スペース+終端文字、文字列長1、メモリ2byte (2) 違う Windows MS-DOSでは 1Ah EOFはファイルの終端を表す。OSによって違う。 EOF は End of File です。念のため。
- Tacosan
- ベストアンサー率23% (3656/15482)
ついでなので: '\0' はコード値 0 を持つ立派な文字ですが, EOF は文字ではありません (規格上は負の整定数, 実際上はほとんどの場合で -1). ということで, getchar などは全ての文字に加えて EOF も返す可能性があるため char ではなく int を返すことになっています.
- SSBBGLUV
- ベストアンサー率47% (11/23)
(1) NULL(nullではなくNULLです)はポインタがどこも指し示していないことを示す値です。 ""は長さ0の文字列です。 ご存知だとは思いますが、C言語ではメモリ上で連続するバイト列の終端に'\0'を置く事により便宜上そのメモリの一部分を文字列として扱うことが出来ます。例えば 'A' 'B' 'C' '\0'と並んでいたら、それは"ABC"という文字列と扱うことができます。この文字列は、メモリ上は4バイトを使用しますが、文字列としては3文字として扱います。""の場合、いきなり'\0'がきている文字列ということになります。従って、1バイトを使用する長さが0の文字列となります。長さが0ですので、当然文字コードもありません。なお、一文字スペース" "の場合は' ' '\0'という2バイトで長さ1の文字列です。 ちなみに、コード表では00hがNULとして定義されていますが、これはコード表での定義であってC言語とは無関係です(NULLではなくNULです)。 ※このヌルという言葉は、色んな所で色んな定義がされているので非常に混乱しやすいものです。 (2) '\0'は(1)の通り文字列の終端を表す値で、EOFはファイルの終端を表す定数です。ファイルの終端に達するとfgetc()などはEOFを返しますが、これはファイルの終端に達したことを示すのみであって特定の文字を読み込んだことを意味するものではありません。なお、一部処理系では特定の文字を読み込んだ場合にEOFを返す場合がありますが、これは特殊な例です。
- TALLY-HO
- ベストアンサー率29% (103/354)
#1です。 混乱されるといけないので他の方と合わせましょうか。 NULL と "" について「文字を数えたり」ということ でしたので「同じ」としました。 厳密には他の方が仰るとおりです。 『NULLポインタ』に限らず『NULL値』というのもあります。 つまり未定,不明な場合をNULLという事にしてるのです。 データベースご存じですか?Excelを高度にシステム化 したような奴なのですが、これに「非NULL制約」という ものがあるんです。""はNULLではないのですが、 この制約がかかってる場所が""(長さ0文字列)だと エラーになります。 つまり、NULLと""は コンピュータ寄りで考えると別物、意味で考えると同じ ということです。
- 1
- 2
お礼
たくさんの回答ありがとうございます。 実はC言語はほとんどやってないのですが、 JAVAよりは、C言語のほうがこの点は詳しいと思った ので、質問させてもらいました。 やっぱり非常に詳しい回答がいただけたので、 よかったと思います(まだ全部読みきれてないのですが)。 本当にありがとうございました。