is??? (例: isprintなど)に対して負の値を与えたときの挙動 (具体的にはEUC漢字の各々のバイトをis??? に食わせたときの挙動)が LinuxとNetBSDでは違うような気がしたので、なんとなく興味を持って 調べてみました。
is??? 系のマクロはctype.hで定義されています。
#define isprint(c) ((int)((_ctype_ + 1)[(int)(c)] & (_P|_U|_L|_N|_B)))_ctype_ という配列に、各々のキャラクタがどういう属性を持つのかを 格納しておいて、is??? で呼ばれたときにそのフラグをチェックするように なっています。 +1されているのはEOF(-1)を食わせたときに配列の外に アクセスしに行かないためだというのをCの256本で読んだことがあります...
このとき、冒頭にあげたように漢字の断片などを(signed)charで受けて それをそのままこういったマクロに食わせてしまうと、符号拡張→負の値が 入る→結果は不定 ということになります。
とりあえずglibc-2.2.5をもってきて調べてみました。 ctype関連はglibc-2.2.5/ctype/ 以下にあります。 細かいことを無視すると以下のような部分が該当しそうです。
(ctype.h) enum { _ISupper = _ISbit (0), /* UPPERCASE. */ _ISlower = _ISbit (1), /* lowercase. */ _ISalpha = _ISbit (2), /* Alphabetic. */ _ISdigit = _ISbit (3), /* Numeric. */ _ISxdigit = _ISbit (4), /* Hexadecimal numeric. */ _ISspace = _ISbit (5), /* Whitespace. */ _ISprint = _ISbit (6), /* Printing. */ _ISgraph = _ISbit (7), /* Graphical. */ _ISblank = _ISbit (8), /* Blank (usually SPC and TAB). */ _IScntrl = _ISbit (9), /* Control character. */ _ISpunct = _ISbit (10), /* Punctuation. */ _ISalnum = _ISbit (11) /* Alphanumeric. */ }; extern __const unsigned short int *__ctype_b; /* Characteristics. */ # define isprint(c) __isctype((c), _ISprint) #define __isctype(c, type) \ (__ctype_b[(int) (c)] & (unsigned short int) type) (ctype-info.c) /* Defined in locale/C-ctype.c. */ extern const char _nl_C_LC_CTYPE_class[]; #define b(t,x,o) (((const t *) _nl_C_LC_CTYPE_##x) + o) const unsigned short int *__ctype_b = b (unsigned short int, class, 128);なので、
const unsigned short int *__ctype_b = (((const unsigned short int *) _nl_C_LC_CTYPE_class) + 128)となりまして、-128までを食わせても大丈夫になっているようです。 また、確認していませんが、どうやら(signed)charの値を与えたときにも unsigned charにキャストした後に食わせたときと同じ結果になるように テーブルを対称に構成しているような感じがします。
といってもソース読めないのでMSDNの解説を 読みます。-1 から 0xffまでの値を食わすことができるようです。
NetBSDのmanを読む限りでは、is???系の関数(マクロ)は、ANSI C準拠であると 表示されていますので、ANSI Cにおけるis???系関数は-1未満の値を食わせたときの 動作は不定になっているのではないかと考えられます。 参考: NEWS OSのドキュメントと ANSI C Rationaleの解説
不定ということは、coreを吐いてもハングアップしてもいいし、 glibcがやってるように、ユーザが意図していると思われる動作を推測して 結果を返してもいいということにはなりそうです。が、もちろんその動作には 移植性がありませんから使用者側で注意しておく必要があります。