8

gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 を使用しています。

のマニュアルページにisalnum()は次のように書かれています:

SYNOPSIS
       #include <ctype.h>

       int isalnum(int c);

ただし、次のようにも述べています。

これらの関数は、unsigned charまたは EOFの値を持つ必要があるcが ...

isalnum()非常に大きな正(または負)の値で爆発することがわかりましたint(ただし、すべてのshort int値を処理します)。

C ライブラリの作成者は、爆発せずにすべての値を処理しない方法でunsigned char実装する権利を留保しているため、渡された int には an の値が必要であるとマニュアル ページに記載されていますか?isalnum()int

4

1 に答える 1

7

The C standard says as much...

In ISO/IEC 9899:1999 (the old C standard), it says:

§7.4 Character handling

The header declares several functions useful for classifying and mapping characters. In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

(I've left out a footnote.) Both C89 and C11 say very much the same thing.

One common implementation is to use an array offset by 1 — a variation on the theme of:

int _CtypeBits[257] = { ... };

#define isalpha(c)  (_Ctype_bits[(c)+1]&_ALPHA);

As long as c is in the range of integers that an unsigned char can store (and there are 8 bits per character, EOF is -1, and the initialization is correct), then this works beautifully. Note that the macro expansion only uses the argument once, which is another requirement of the standard. But if you pass random values out the stipulated range, you access random memory (or, at the least, memory that is not initialized to contain the correct information).

于 2012-07-24T04:13:01.390 に答える