web-dev-qa-db-ja.com

NULLは常に偽ですか?

CでNULLが常にfalseに変換されると仮定しても安全ですか?

void *somePtr = NULL;

if (!somePtr) {
  /* This will always be executed? */
}

または、NULLの値に対して明示的なチェックを行う必要がありますか?

49
Sydius

はい。 Cはゼロ以外の値を真、ゼロ値を偽とみなすため、NULLは偽と評価されます。 NULLは基本的にzeroアドレスであり、比較ではそのように扱われます。ブールチェックのためにintに昇格されると思います。私はおそらくチェックを明示的にするだろうが、Cに精通している人なら誰でもあなたのコードが読めると期待するだろう。

CおよびC++プログラミングでは、2つのNULLポインターが等しいことを保証されます。 ANSI Cは、整数型との比較でNULLポインターが0に等しいことを保証します。さらに、マクロNULLはNULLポインター定数、つまり値0(整数型として、またはvoidへのポインターに変換)として定義されているため、NULLポインターはNULLと等しくなります。

参照: http://en.wikipedia.org/wiki/Null_pointer#Null_pointer

51
tvanfosson

何を想定しても安全ではありません。

また、テスト対象について明示的なチェックを行うとより明確になります。

18
akatakritos

「C」言語は、(void *)0が実際に有効なポインターになる可能性のある時代からのものです。 8080およびZ80マイクロプロセッサのアドレス0に割り込みベクトルがありました。そのようなアーキテクチャの選択に直面して、ヘッダーファイルにNULLの値を宣言させる以外に何もできませんでした。 NULLが(void *)0(0xffffが次の代替手段)に等しくないため、if()ステートメントに未定義の動作を与えるいくつかのコンパイラーがあります。

C++はこれに慈悲深く終止符を打ち、ヌルポインターは0から割り当て可能であり、0に対してテスト可能です。

17
Hans Passant

はい(少なくとも標準に準拠したCコンパイラの場合!)

comp.lang.c FAQ から:

Q:NULL以外のポインターをテストするための短縮ポインター比較「if(p)」は有効ですか? nullポインターの内部表現がゼロ以外の場合はどうなりますか?

A:常に有効です。

11

NULLは単なるプリプロセッサ定義です。 stdio.hにあります。通常、非常識な人だけがそれを再定義しますが、それは可能です。例:

#include <stdio.h>
#ifdef NULL
#undef NULL
#define NULL 1
#endif

void main()
{

        if (NULL)
                printf("NULL is true\n");
        else
                printf("NULL is false\n");
}

このコードは「NULL is true」を出力します。あなたが私を信じないなら、それを試してください。あなたのコンパイラは、あなたが何かおかしなことをしているという警告さえしないかもしれません。

5
bdowling

C-FAQの 質問5. を参照するだけです。この正確な質問に答えます。

2
anon

NULLは、メモリ内の役に立たない/存在しない場所を指すことが保証されている定数ポインタとして定義されています。 NULLのほとんどの実装は((void *)0)しかし、そうである必要はありません。

2
dreamlax

はい、ほとんど。

まず、NULLはtypedefです。以前に含まれていたヘッダーで言うことで、私はあなたを大いに混乱させることができました

_#define NULL 1_

これはあまり意味がないかもしれませんが、いつから他の人のコードが意味をなしたのでしょうか? :)

また、おそらく構文的には安全ですが、意味的には正しくありません。 NULLは「何もない」ことを意味し、trueまたはfalse、ブール値、intまたはstringのいずれでもありません。それは「無のための象徴」を意味します。 NULLのテストは哲学的な問題に似ています。木が森に落ち、if(listener)の場合、音がしますか?

みなさんにお願いし、NULLに対するテストについて明確にしてください。

0
Matt