■NULL判定って書くのは止めよう!
【NULL判定】
【ヌル判定】
【ナル判定】
って書くのは止めよう!
【NULLポインタ判定】
【空文字列判定】
【終端文字¥0判定】
と書こう。
■推奨例:空文字列を判定する関数
#include <stdio.h>
char *isEmptyString(const char *p){
if(p == NULL) {
return "NULLポインタ";
}
if(p[0] == '\0'){
return "空文字列";
}
return "文字列";
}
int main(void) {
puts(isEmptyString(NULL)); //NULLポインタ
puts(isEmptyString("")); //空文字列
puts(isEmptyString("abc"));//文字列
}
NULLポインタと終端文字¥0、
NULLポインタと空文字列””を
しっかり区別した書き方です。
■非推奨例1:いきなりstrcmp
#include <stdio.h>
#include <string.h>
char *isEmptyString(const char *p){
if(strcmp(p,"") == 0){
return "空文字列";
}
return "文字列";
}
int main(void) {
puts(isEmptyString(NULL)); //NULLポインタ
puts(isEmptyString("")); //空文字列
puts(isEmptyString("abc"));//文字列
}
引数のポインタが空文字列かどうか判定したい時、
いきなり
strcmp()を使って第二引数にNULLポインタを渡してはいけません。
NULL参照が発生して
プログラムが異常終了してしまう可能性があります。
■非推奨例2:いきなりstrlen
#include <stdio.h>
#include <string.h>
char *isEmptyString(const char *p){
if(strlen(p) == 0){
return "空文字列";
}
return "文字列";
}
int main(void) {
puts(isEmptyString(NULL)); //NULLポインタ
puts(isEmptyString("")); //空文字列
puts(isEmptyString("abc"));//文字列
}
NULLポインタのチェックをしてからstrlen(p)を呼び出しましょう。
又、strlen(p) 関数を呼び出すため、
関数呼び出しのオーバーヘッド分プログラムの実行速度が
遅くなります。
■非推奨例3:NULLと’\0’の混乱
#include <stdio.h>
char *isEmptyString(const char *p){
if(p == '\0') {
return "NULLポインタ";
}
if(p[0] == NULL){
return "空文字列";
}
return "文字列";
}
int main(void) {
puts(isEmptyString(NULL)); //NULLポインタ
puts(isEmptyString("")); //空文字列
puts(isEmptyString("abc"));//文字列
}
上記のコードはNULLポインタと終端文字¥0の区別がついていない
初級者の間違いです。
ポインタpを終端文字\0と比較したり
一文字のp[0] と NULLポインタを比較しています。
■非推奨例4:NULLポインタ判定が遅い
#include <stdio.h>
char *isEmptyString(const char *p){
if(p[0] == '\0' && p != NULL){
return "空文字列";
}
if(p == NULL){
return "NULLポインタ";
}
return "有効文字列";
}
int main(void) {
puts(isEmptyString(NULL)); //NULLポインタ
puts(isEmptyString("")); //空文字列
puts(isEmptyString("abc"));//有効文字列
}
上記のコードは
p != NULLの判定をする前に
p[0] を参照してしまった例で
これでは p がNULLの時NULL参照が発生してしまいます。
先に p != NULL の判定を行う必要があります。
参考:
C-FAQ5.13: “ヌル”とか”NULL”とか”ナル”という単語が無造作に使われるときは以下のどれかを意味する。
http://www.kouno.jp/home/c_faq/c5.html#13