[PR]

文字関数(isalnum, toupper など) 使用上の注意

戻る

 文字関数の引数に char 型変数を渡すと、関数が期待するとおりに動作しない場合がある。

原因:
 文字関数の引数型は int 型です。
 文字関数は、与えられた引数値が EOF か 0x00 〜 0xFF(UCHAR_MAX) の場合に正しく動作します。
 一方、char 型の 0x80 〜 0xFF は、数値 -128 〜 -1 を意味します。
 数値 -128 〜 -1 は 32 ビット int 型では 0xFFFFFF80 〜 0xFFFFFFFF と表現されます。
 このことは、文字関数が引数値に EOF か 0x00 〜 0xFF(=255) を期待することに反します。

対処法:
 この問題は、引数に渡す char 型変数を unsigned char 型に変換することで回避できます。
 unsigned char 型の 0x00 〜 0xFF は数値 0 〜 255 を意味し、int 型でも 0x00 〜 0xFF と表現されます。


//*********************************************************
// 引数値が 0x00 〜 0xFF の範囲であれば真を、さもなくば偽を返す。
//*********************************************************
int is_char( int c )
{
	return ( c >= 0 ) && ( c <= 0xFF );
}//is_char

//*********************************************************
// 文字関数引数の動作確認
//*********************************************************
int main( void )
{
#define LINEWIDTH 0x1F // LINEWIDTH 毎に改行
	int  i;
	char c;

	puts( "引数に char 型変数を渡した場合:" );
	for( i=c=0; i <= 0xFF; c = (char)++i )
	{
		if ( 0==(i&LINEWIDTH) ) printf( "0x%02x: ", i );
		printf( "%s%s",
			(is_char(c) ? "○" : "×"),
			((LINEWIDTH == (i & LINEWIDTH)) ? "\n" : "") );
	}
	puts("");

	puts( "unsigned char に変換した場合:" );
	for( i=c=0; i <= 0xFF; c = (char)++i )
	{
		if ( 0==(i&LINEWIDTH) ) printf( "0x%02x: ", i );
		printf( "%s%s",
			(is_char((unsigned char)c) ? "○" : "×"),
			((LINEWIDTH == (i & LINEWIDTH)) ? "\n" : "") );
	}

	return 0;
#undef LINEWIDTH // #define LINEWIDTH
}//main

実行結果

引数に char 型変数を渡した場合:
0x00: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0x20: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0x40: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0x60: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0x80: ××××××××××××××××××××××××××××××××
0xa0: ××××××××××××××××××××××××××××××××
0xc0: ××××××××××××××××××××××××××××××××
0xe0: ××××××××××××××××××××××××××××××××

unsigned char に変換した場合:
0x00: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0x20: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0x40: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0x60: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0x80: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0xa0: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0xc0: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○
0xe0: ○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○○

関連

printf, fprintf, sprintf 使用上の注意
1行注釈(//)使用上の注意
右シフト演算子(>>)使用上の注意



Google
ご意見・ご感想をお聞かせ下さい。匿名で送信できます。

 * 返信が必要な場合には postmaster@katsura-kotonoha.sakura.ne.jp へ直接メールしてください。

水無瀬 優 postmaster@katsura-kotonoha.sakura.ne.jp