ユーニックス総合研究所

  • home
  • archives
  • c-null-hantei

C言語でnull判定する方法【NULL, 比較】

  • 作成日: 2024-03-11
  • 更新日: 2024-03-11
  • カテゴリ: C言語

この記事ではC言語でNULL判定する方法を解説します。
NULLの扱いはC言語では非常に頻出する問題です。

NULLとは何か? NULLの実装がどうなっているか?
など基本的なことからNULLの比較まで詳しく解説します。

C言語や他の言語を扱うYoutubeも公開しています。
興味がある方は以下のリンクからご覧ください。

Youtubeの当チャンネル

NULLとは何か?

NULL」とは「何も無いことを表すキーワード」になります。
存在しないことを表すための表記です。

C言語では処理系によってNULLが定義されています。
これはマクロで実装されることが多いです。

C言語におけるNULLはポインタ変数の初期化や比較などに使われます。

ポインタ変数はアドレスを格納する変数ですが、初期値があった方が便利です。
C言語では変数は初期化すると初期値が入ります。
ですのでポインタ変数にも初期値となる何かが必要です。

その必要な何かNULLです。

NULLがあることでポインタ変数になにも代入されていないという状態を表現できます。
これによって「ポインタが空っぽ」という文脈も可能になります。

NULLは数値の0と同様にその必要性から生まれたものです。

関連記事
C言語のポインタをC言語歴17年が解説
C言語の終端を表すEOF, NULL, ナル文字について

NULLの実装は?

NULLの定義は処理系(コンパイラ)によります。
処理系によってはNULLは以下のように定義されることが多いです。

#define NULL ((void *) 0)  

数値の0void型のポインタにキャストしただけです。
これがNULLの正体です。

void型は関数の返り値が存在しないことを表すほか、汎用的な型としても知られています。
void型のポインタはあらゆる型にキャストすることができ、C言語で型を抽象化したい時によく使われます。

つまりNULLとは「抽象的な0」と言うことができます。

ポインタ変数とNULLの比較

ポインタ変数とNULLを比較する場合は

  • イコール(==)演算子
  • ノットイコール(!=)演算子
  • ノット(!)演算子

などを使います。

イコール演算子

イコール(==)演算子でポインタ変数とNULLを比較する場合は以下のようにします。

#include <stdio.h>  

int main(void) {  
    int *p = NULL;  

    if (p == NULL) {  
        puts("this is null");  
    } else {  
        puts("not null");  
    }  

    return 0;  
}  

上記のコードをコンパイルして実行すると以下のように表示されます。

this is null  

イコール演算子は両辺のオペランドが等しい時に真になります。
ポインタ変数pにはNULLが入っていますのでp == NULLの結果は真です。
そのためthis is nullと表示されます。

これはNULL((void *) 0)defineされることが多いので、以下と同じです。

#include <stdio.h>  

int main(void) {  
    int *p = NULL;  

    if (p == ((void *) 0)) {  
        puts("this is null");  
    } else {  
        puts("not null");  
    }  

    return 0;  
}  

上記の実行結果は先ほどと同じになります。
GCCコンパイラの場合はオプション-Eでプリプロセス結果を見ることができます。

ノットイコール演算子

ノットイコール(!=)演算子を使う場合は以下のようなコードを書きます。

#include <stdio.h>  

int main(void) {  
    int *p = NULL;  

    if (p != NULL) {  
        puts("not null");  
    } else {  
        puts("this is null");  
    }  

    return 0;  
}  

上記の実行結果は

this is null  

になります。
ノットイコール演算子は左右のオペランドが等しくない時に真になります。
上記の例ではポインタpにはNULLが入っています。
ですのでp != NULLは「pはNULLではない」という式ですので、偽になります。
その結果、this is nullと表示されます。

ノット演算子

NULLの定義は((void *) 0)になっていることが多いため、ノット(!)演算子で比較した場合は真になります。
つまり以下のようなコードを書けます。

#include <stdio.h>  

int main(void) {  
    int *p = NULL;  

    if (!p) {  
        puts("this is null");  
    } else {  
        puts("not null");  
    }  

    return 0;  
}  

上記のコードの実行結果は以下になります。

this is null  

空文字列かどうかの判定

文字列の場合は空文字列かどうか判定する場合はstrlen()などを使います。
strlen()は文字列の長さを得る関数です。
文字列が空の場合はゼロを返してきます。
文字列の変数がNULLかどうか判定したい場合は前述のノットイコールなどを使います。

#include <stdio.h>  
#include <string.h>  

int main(void) {  
    const char *p = "Hello, World!";  

    if (strlen(p) == 0) {  
        puts("empty");  
    } else {  
        puts("not empty");  
    }  

    return 0;  
}  

strlen()はNULLポインタを渡したときにNULLかどうかチェックしないので不安な方はNULLのチェックもif文に入れておくといいでしょう。
もっともこれはいささか心配しすぎかもしれません。

#include <stdio.h>  
#include <string.h>  

int main(void) {  
    const char *p = NULL;  

    if (p == NULL || strlen(p) == 0) {  
        puts("empty");  
    } else {  
        puts("not empty");  
    }  

    return 0;  
}  

上記のコードを実行するとemptyと表示されます。
OR(||)で連結した条件文は先にp == NULLが判定されます。
そしてp == NULLは真なのでその段階で条件式の判定が中断します。
結果的にp == NULLは真になり、emptyと表示されます。

おわりに

今回はC言語のNULL判定について解説しました。
なにか参考になれば幸いです。