• ベストアンサー

C++のNULLは意味があるの?

タイトルの通りです。 0で全て済むのに、わざわざNULLを使う必要が分かりませんし、私は全く使った事がありません。 ただ0と書くと数値かポインターかすぐには分からない からというのは、あまり対した理由にはなりそうも無いし。 ほかの人がNULLを使っているのをそのまま参考にしたと言うのが多いかもしれないですね。

質問者が選んだベストアンサー

  • ベストアンサー
  • furlong
  • ベストアンサー率50% (17/34)
回答No.11

#4です。 C++で考えられる唯一の例外は可変引数の関数を呼び出すときです。この場合、"0"をintの0として扱うべきかdoubleの0.0として扱うべきか無効ポインターとして扱うべきか、コンパイラーが判断できない為、明示的にキャストして型を教える必要があります。この場合、単に0と書くよりはNULLの方が少しマシといった程度で、移殖性を考えると危険であることに変わりはありません。 #8他について、無効ポインターの値(ビットパターン)は処理系定義ですが、上に示した特殊な状況を除き、無効ポインターの値が何であろうとコンパイラーが定数0を無効ポインターに変換してくれます。ちなみに、mallocが失敗したときの値は、厳密にいうとNULLではなくて無効ポインター(a null pointer)です。 #10について、この場合、0と書いてもNULLと書いても同じです。"C *c = (C *)0;"の時点でcの値は無効ポインターになります。そして、無効ポインターを他の型のポインターにキャストすると必ず無効ポインターになります。

その他の回答 (10)

  • jmh
  • ベストアンサー率23% (71/304)
回答No.10

自信ないですが、C++でキャストした0は危険だと思います。 無効なポインタの"値"が0でない場合に、  struct A { ... };  struct B { ... };  struct C: A, B { ... };  C *c = (C *)0;  B *b = c; の b が無効なポインタになるのでしょうか? (C *)0 は定"整"数の0ではないので、無効なポインタには変換されないと思います。 素朴に考えると最後の行は  B *b = (c == (無効なC *) ? (無効なB *) : (B *)((char *)c + sizeof(A)); と同じコトになる気がします。 今、(無効なC *) != (C *)0 なので  b == (B *)sizeof(A) になりませんか?

  • jmh
  • ベストアンサー率23% (71/304)
回答No.9

no.5 jmh です。 g++ には、__null というキーワードがあって、  int n = NULL; // #define NULL __null には警告できるみたいです。でも、より明らかに間違えた感じの  int *n = 1 + 2 - 3; // == 0 は素通りみたいです。

  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.8

自分で読み返して「何を言ってるのかよくわからないかも?」と感じたので、もう一度。 ・インターフェース上NULLと記述することを要求している部分に関しては素直にNULLを使うべき malloc()など「失敗したときにはNULLが返される」というインターフェースの場合、わざわざ0と比較するよりもNULLで比較するべきです。 16bit版のMS-CやVC++では0は16bitなのvoid far *malloc()の戻り値(32bitアドレス値)と比較することは推奨されません。 この場合は#define NULL 0Lと定義されたNULLと比較するべきです。 ・0が(char *)0や(void *)0と同じ形式である保証はない アドレス値のフォーマットは処理系依存です。 NULLは「インターフェース上NULLが使われることが明らかな場合」に使うべきで、「NULL」と「正しくキャストされた0」を便宜使い分けるべきです。 と、言いたかったわけです。 可読性/移植性の問題からキャストを伴わない0をアドレス値として利用することは勧められません。

graphaffine
質問者

補足

toysmithさん、今晩は。それから他の方にも纏めて 返信です。 まず、大前提はタイトルにも有りますように、C++ です。私はC固有の話は詳しくありません。 質問の趣旨は可読性以外にNULLを使う必要性があるか?ということですがどうやら無いようですね。この点に関しては了解しました。ということで可読性の件は終わりにします。 派生事項として、NULLと移植性との関係ですが、ヘッダーファイルを見ましたがVCではNULLは0と 定義されていました。従って、NULLでも0でも処理的には同じであるということが分かりました。 >NULLは「インターフェース上NULLが使われることが明らかな場合」に使うべきで、 >「NULL」と「正しくキャストされた0」を便宜使い分けるべきです。 #4の追伸のように単独の0をポインター値として使う場合、コンパイラーにより適切に変換される。従って、0を キャストする必要が無いと取ったのですがこの理解は間違っているのでしょうか。

noname#30727
noname#30727
回答No.7

ヌルポインタをNULLと表現するのは、やはり可読性の為だと思います。 graphaffine さんが、変数名に対しては可読性を向上させる手法を認めているにもかかわらず、定数に対して窮屈な考え方をするのは、客観的にみて不自然です。 #define、const int、enum などで定義された名前のうち、0と同じものをわざわざ定義する必要はないと言っているように思えます。 0は式において「偽」であり、特別だと言えますが、NULLを0の中でもさらに特別なものと位置づけるコーディングスタイルだという事です。

  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.6

まず理解しなくてはいけないのは「C,C++には組み込み定数が存在せず、NULLはプリプロセッサシンボルでしかない」ということです。 プリプロセッサがプリプロセッサシンボルを値に変換するときに文法を意識することを期待できません。 ANSI以前のCではNULL=0というのはUNIXにおける慣例にすぎず、NULLで示される無効ポインタは0という保証はありませんでした。 またint16ビット、アドレス32bitのコンパイラではNULLは0Lである必要がありました。 移植性の観点から無効ポインタを0と記述することは問題がありました。 しかし、32bitアドレスと16ビットアドレスを使い分ける必要のある場合などは「何が何でも向こうポインタはNULL」と考えると問題が発生する場合があります。 C/C++ではアドレス値の形式は処理系依存なので(char *)0とか(long *)0のように明示的なキャストを伴う値を使った方が移植性は向上します。

  • jmh
  • ベストアンサー率23% (71/304)
回答No.5

私は逆に次のはどちらも警告かエラーであってもいいのになぁと思います。  char *p = 0;  int n = NULL;

  • furlong
  • ベストアンサー率50% (17/34)
回答No.4

C++でNULLと書くのは昔のCの名残だと思います。プロトタイプ宣言をせずに関数を呼ぶとき、コンパイラーが引数の型を知らないので、整数0なのかポインターNULLなのか、教えてあげる必要があります。C++では可変引数の関数を呼ぶ場合ぐらいにしか意味がありません。(整数とポインターの取り扱いが異なるCPUを使う場合) 但し、本気で移殖性を考えるとNULLは中途半端です。神経質に考えるとintへのポインターのNULLとcharへのポインターのNULLは取り扱いが違う可能性がある為、万全を期すには個別にキャストを付けるしかないようです。 追伸:プロトタイプ宣言がある場合は、仮にNULLポインタの値が物理的に0以外の特殊な値であっても、コンパイラが0をNULLに自動的に変換してくれます。これは保証されています。

graphaffine
質問者

補足

furlongさん解答有り難う御座います。 >C++でNULLと書くのは昔のCの名残だと思います。 ということは、現在は実質的な意味は無いということですね。C++はプロトタイプ宣言が必須ですからね。 あと、移植性を考えた場合は0を指定した方が良いということですね。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.3

NULLって0x00とは限らないはずですよ。 コンパイラ依存だったはずです。 もしそういうコンパイラを使ったら、graphaffineのソースはすべてアウトですね。

graphaffine
質問者

補足

#4追伸を御参照下さい。

  • mrumesuke
  • ベストアンサー率45% (254/557)
回答No.2

NULLの値は0であるけれど、0はNULLと等しいのでしょうか。 ある日突然、あるいは環境によってNULLの定義が変わってしまったらどうするのでしょう。 また、ソースの品質と言うことを考えてください。 多人数でプロジェクトを組んだとき、あるいは何らかの形でソースを公開したとき、他人はあなたのコードを見てどれだけ理解できるのでしょうか。場合によっては誰かに引き継がなくてはならないこともあるでしょう。マジックナンバーだらけのコードの可読性は低く、その結果品質は低下します。適切にNULLとしておけば、引き継いだ相手を「この0の意味はなんだろう」と悩ませることもないでしょう。 個人で完結するものならどんなコーディングスタイルでも構わないでしょうけど。

graphaffine
質問者

補足

前半については#4追伸を御参照下さい。 また、後半は0は特別であり一般的なマジックナンバーと 同列には扱えないと思っています。 実際一般的な場合は変更があり得ますが、0は変更の必要はありませんし。

noname#4252
noname#4252
回答No.1

NULLを使うとポインタだと分かるのに わざわざ0を使う理由が分かりません。 結局同じだからといっても NULLと書くと可読性がいいと思うのですが。

graphaffine
質問者

補足

arrowrootさん、解答有り難う御座います。 可読性については変数の命名法等でカバーできるので あまり気にしていません。ので、他に何か理由があるのか知りたかったのですが、どうやら無いようですね。 >NULLを使うとポインタだと分かるのに >わざわざ0を使う理由が分かりません。 万が一、NULLポインターの内部形式が変わった場合でも ヘッダーを切り替える必要はありません。 #4の追伸参照。私の質問はこの追伸を踏まえたものです。

関連するQ&A

  • Cで言うNULLは「C++では0をリテラルとする」みたいな事を、

    Cで言うNULLは「C++では0をリテラルとする」みたいな事を、 どこかで昔、読んだのですが今でもそうでしょうか? (Cの場合、厳密にはdefine定義でNULLとしている(た)のでしょうが…) 最近のCとC++の言語仕様に詳しい方、お願いします。 気分的にはC++の場合、自分はポインタ初期化を0で行う事が好きなので、 他の人はどうしてるんだろうと、気になった所から生まれた疑問です。 //例:↓ClassXのコンストラクタの実装 ClassX::ClassX(void) :mPtr(0) { } }

  • #define NULL ((void *)0) の弊害

    よく話題にされるヌルポインタについての疑問です。 定数の0は、それがポインタと解されるべき文脈では ヌルポインタに読み替えられますが、 可変長引数のようにポインタであることがコンパイラには判断できない文脈では、 明示的にキャストしてやらなければなりません。 このとき、#define NULL 0 と定義されている処理系では、 NULLを使っても定数の0を書いたのと全く同じであり、 上のような場合におけるキャストの必要性からは逃れられません。 しかし、たまたま自分の処理系で #define NULL ((void *)0) と定義されていれば、 キャストを行わなくてもNULLを使うことによって正しく動いてしまいます。 ということは、#define NULL ((void *)0) と定義された処理系しか 使ったことの無いプログラマは、 「NULLを使うこと自体が、これはポインタだよという意志表示になる」 と錯覚してしまう危険性をはらんでいることになります。 この人の書いた「NULLを使い、必要なキャストを省略しているソース」を、 #define NULL 0 と定義された処理系でコンパイルすると 正しく動作しない可能性があります。 こういう弊害があるにもかかわらず、 ANSI Cでは #define NULL 0 のほかに #define NULL ((void *)0) も許しているのは、 一体なぜなのでしょうか。 メリットもあるのでしょうか?

  • nullの概念

    nullの3つの概念と言われる、空文字、空ポインタ、空文の意味と必要性がいまいちわかりません。 ご存じの方ぜひ教えてください。

  • NULL値をゼロとして扱うには?

    JavaScriptでNULL値をゼロとして扱いたいのですが、"parseFloat"や"eval"などで変換してもはゼロ数値として扱ってくれません。やはり、"NaN"や"Undefined"かどうか判断して、そうであった場合は"0"に変換するというステップが必要なのでしょうか? なんかスムーズじゃなくて納得できません。

  • C言語の勉強中です

    C言語の勉強中です。自分の参考にしている本でよくわからないところがあったので教えてください 本には、NULLポインタは、すべてのビットが0であり、どこのアドレスも指さないポインタのことと書いてあるのですが、アドレスは0から始まるから、実際はアドレスの0番地を指していますよね? どこのアドレスも指さないと言いつつ、実際は0番地を指しているあたりがよくわかりないので教えてください

  • Accessで値がnullの場合は計算せずにnullをかえす方法

    Accessについて、教えてください。 クエリで抽出しているときに、フィールド1とフィールド2の数値を掛け算した値をフィールド3に表示したいと思っています。(小数点1位まで表示) フィールド1とフィールド2は値がnullの場合もありますが、この場合は「0」として扱うのではなく、そのまま計算結果もnullにしたいと思っています。 最初は単純に フィールド3: ROUNDMS2(ROUNDMS([フィールド1],1)*ROUNDMS([フィールド2],1),1) とクエリに表記したのですが、この場合「フィールド1」や「フィールド2」がnullの場合は#ERRORが表示されました。 次に、IFでフィールド1やフィールド2がnullの場合は計算せずにnullをかえしてもらおうと下記のような文をつくりました。 フィールド3: IIf([フィールド1]=Null,Null,IIf([フィールド2]=Null,Null,ROUNDMS2(ROUNDMS([フィールド1],1)*ROUNDMS([フィールド2],1),1))) これでもやっぱり#ERRORが表示されます。 いろいろと検索したのですが、nullを0として扱う例は多数見つけられましたがnullのまま扱う例が見つけられませんでした。 勘違いしているところがあるかもしれませんが、アドバイスよろしくお願いいたします。

  • 「NULLポインタ」と「演算の結果としてのアドレス0」との比較

    ものすごく基本的な疑問です。。。 「C言語FAQ日本語訳」http://www.kouno.jp/home/c_faq/ ここの「05.ヌルポインター」を見ると以下のような意味の記述があります。 「NULLポインタは他のどんなポインタの値とも区別可能で、有効なポインタと比較しても等しくなる事はない」 「ポインタを書くべき場所に書かれた定数0はコンパイル時にNULLポインタに変換される」 そこで以下のプログラムを Borland C++ 5.5 for Win32 でコンパイル・実行してみたところ、 p1 == p2 とりました。これって変ですよね? p1 は明示的に定数0で初期化しているのでNULLポインタですが、p2 は演算の結果としてアドレス0番地を指しているので、NULLポインタでは無いですよね? これはコンパイラが間違っていると思って良いのでしょうか? #include <stdio.h> int main() { char *p1,*p2; p1 = 0; p2 = (char *)1; p2--; if(p1 == p2){ printf("p1 == p2"); } else{ printf("p1 != p2"); } return 0; }

  • フォームを開くときのwhere条件式でnull値のものに絞りたい

    VBAの記述で、フォームを開くときにレコードの抽出条件を指定できますが、その際,指定したフィールドの値がNullのもの、逆にNullLでないものという条件の与え方はできないのでしょうか? 値がある文字列と等しいとかある数値や日付以上といった条件式はヘルプでみるのですが、NullかNullでないといった判断をさせる条件式が参考書等でもみあたらないのですが。  それとも何か違うやりかたがあるのでしょうか?ご存知のかたは教えてください。

  • データベースのINT型項目にNULLはNG?

    以前、知り合いからデータベースのINT型の項目には出来ればNULLを許可しない(NOT NULL)方がいいと聞いたことがあるのですが、本当でしょうか? 現在不動産の物件データを登録するためのシステムを作成しており、 データベースの設計を行なっている最中なのですが、 例えば金額や面積など数字しか入力されない項目はINT型にしたいと考えています。 ※データベースはMySQLになります。 ただし、 物件データ登録時に数字項目に何も入力されなければ「NULL」、 0以上の数値を入力されている場合にはそのままその数値をデータベースに登録したいと考えています。 ※0を入力されている場合には「0」をそのまま入れたいです。 INT型の項目にはNULLを入れるのを避けた方がいい場合には、0を入れるような仕様に変更しようと考えているのですが、その辺のことについて教えて頂けると助かります。 ざっくりとした質問で申し訳ございませんが、宜しくお願い致します。

    • ベストアンサー
    • MySQL
  • テキストデータでNULL?

    こんにちは。会社の人がテキストエディタでファイルを開いて、このデータはNULLが入っているからおかしいとかブツブツ言っていました。 データの中身はバイナリデータではなく、固定長、またはCSVファイルのような事を言っていました。 そこで疑問に思ったのですが、固定長、またはCSVでNULLなんてあるんでしょうか?たぶん、空文字列の事をさしてNULLと言っているような気がするのですが、テキストデータにNULLは存在するのでしょうか?

専門家に質問してみよう