をテストするとNULL
、を使用するコードがたくさん表示されます!var
。より明示的なのではなく、この種のテストを使用する理由はありますかvar == NULL
?同様if (var)
に、アイテムがnullでない場合の正しいテストでしょうか?
4 に答える
の違い:
!var
と
var == NULL
var
2番目のケースでは、がポインタ型ではなくNULL
、キャスト(のような)で定義されている場合、コンパイラは診断を発行する必要があります(void *) 0
。
また、(コメントで@bitmaskが示しているように)マクロを使用するには、マクロNULL
を定義する標準ヘッダーを含める必要がありますNULL
。Cでは、マクロNULL
は便宜上いくつかのヘッダーで定義されています(、、、、stddef.h
などstdio.h
)。stdlib.h
string.h
それ以外の場合、2つの式は同等であり、好みの問題です。より快適に感じるものを使用してください。
そして、2番目の質問は、上記の違いとif (var)
同じです。if (var != NULL)
var == NULLバージョンには、1つの大きな利点があります。それは、コンパイラーと静的アナライザーが1つの特定の一般的なバグを見つけることを可能にすることです。
「var」がポインタではなく、割り当てられた変数であるとします。if(!var)
その場合、検出されないまま通過するバグになります。
NULLはしばしばとして宣言され#define NULL ((void*)0)
ます。この宣言は標準では必須ではありませんが、最も一般的な宣言の1つです。半分まともな型チェックを備えたコンパイラは、次のようなコードに対して警告を出すことができます。
int var = ...;
if(var == NULL) // compiler warning, var is not a pointer
上記の利点とは別に、!
演算子は論理演算子であり、ポインターではなくブール変数で使用されることを意図しているため、演算子を使用しないこともスタイル的に正しいです。Cには強い型付けがないため、これは機能します。
この件ではMISRA-Cに従うことをお勧めします。これは、NULLまたはゼロに対するチェックを明示的にする必要があることを示しています。if(x != NULL)
ではなくif(x)
。これらのルールの理論的根拠は、より読みやすいコードです。とにかくまったく同じマシンコードに変換されるので、コードを読みやすくすることに害はありません。
ISO / IEC 9899規格は、次のように述べています。
言語の時点で:値を持つ整数定数式
0
、または型にキャストされたそのような式void *
は、nullポインター定数と呼ばれます。nullポインター定数がポインター型に変換される場合、nullポインターと呼ばれる結果のポインターは、任意のオブジェクトまたは関数へのポインターと等しくないことが保証されます。ライブラリの時点で:
NULL
実装定義のnullポインタ定数に展開されるマクロです。
つまり、あなたが与える表現は等しく「正しい」ということです。ある形式を別の形式よりも好む理由は、主に好みの問題です。
C標準から:
算術型とポインタ型はまとめてスカラー型と呼ばれます。
単項+または-演算子のオペランドは算術型でなければなりません。〜演算子の整数型。の!演算子、スカラー型。
論理否定演算子の結果!オペランドの値が0と等しくない場合は0、オペランドの値が0と等しい場合は1です。結果の型はintです。式!Eは、(0 == E)と同等です。
だから、それはあなたの質問に答えるはずです。