[迷信] isalpha 関数の引数は char 型

isalpha 関数に限ったことではありませんが、<ctype.h> ヘッダで宣言される is 系関数は、次のように int 型の引数を取ります。

int isalpha(int c);

このこと自体もよくある間違いなのですが、問題はここからです。すなわち、is 系関数の引数が char 型だと事実誤認しているために、あるいは int 型であることを知っていたとしても、実引数として渡すことができる値に制約があることを知らないために、危険なコードを書いてしまうことがよくあるのです。

is 系関数に実引数として渡すことができる値は、0 ~ UCHAR_MAX または EOF だけです。通常は問題ないのですが、多バイト文字を含む文字列の各要素を順に is 系関数で調べる場合などは、is 系関数に負の値を渡してしまうことになります。

そうです。char 型が符号付きか符合無しかは処理系定義ですので、char 型が符号無しの環境でたまたま動いていたとしても、char 型が符号付きの環境に移植したとたん、不可解な動作をしたり、クラッシュしたりすることになるのです。

is 系関数に渡す実引数は、fgetc 関数の返却値のような場合はそのままで構いませんが、char 型の値を渡すときには、明示的に unsigned char にキャストしなければなりません。

const char str[] = "abc123";
for (char* s = str; *s != '\0'; s++)
{
  if (isalpha(static_cast<unsigned char>(*s)))
  {
    ...
  }
}

分かっていてもよく間違うもので、特に、述語として is 系関数をアルゴリズム関数に渡す場合など、コールバックでは要注意です。