サイトマップ / C言語講座>出入り口>総目次>目次:バグ対策>整数の取り得る範囲
[整数の内部表現]←このソース→[NDEBUGマクロとassert( )]
/* 今日は、printf( ) で整数を表示する際に、変数が書式指定子の範囲を超えていたら、どうなるかについて実験します。
整数の取り得る範囲については、limits.h の中で記号定数を使って、次のように記述されています。
CHAR_BIT 8 // char 型は8ビット
CHAR_MAX UCHAR_MAX // char 型とunsigned char 型の最大値は同じ
CHAR_MIN 0 // char 型の最小値
INT_MAX +32767 // int 型の最大値
INT_MIN -32768 // int 型の最小値
LONG_MAX +2147483647L // long 型の最大値
LONG_MIN -2147483648L // long 型の最小値
SCHAR_MAX +127 // signed char 型の最大値
SCHAR_MIN -128 // signed char 型の最小値
SHRT_MAX +32767 // short 型の最大値
SHRT_MIN -32768 // short 型の最小値
UCHAR_MAX 255U // unsigned char 型の最大値
UINT_MAX 65535U // unsigned int 型の最大値
ULONG_MAX 4294967295UL // unsigned long 型の最大値
USHRT_MAX 65535U // unsigned short 型の最大値
// unsigned : 符号なし // signed : 符号あり
上に示したのはあくまでも1例で、処理系によって値が異なる可能性があります。
重要:特定の数字をソースコードに書き込んではいけません。
int x = INT_MAX; などと、記号定数を使って記述して下さい。その際、limits.h をインクルードして置くのを忘れないで下さい。
今回は、幾つかの型の最大値を表示し、次いで、同じ書式指定子を使って、それを1越える値を表示することを試みます。結果は、異常な値を表示します。また、最小値を表示し、次いで、それより1小さい数を表示することも試みます。
ソースプログラムを見て下さい。2組の printf( ) が並んでいます。上側の文は、かなり複雑な形をしていて、一見しただけでは、何が表示されるかわかりません。まずは、コンパイルして、実行して見ましょう。
ソース: printf("%d\n", SCHAR_MIN );
結 果: -128 (OK!)
ソース: printf("%d\n", SCHAR_MAX);
結 果: 127 (OK!)
ソース: printf("%d\n", SHRT_MIN);
結 果: -32768 (OK!)
ソース: printf("%d\n", SHRT_MIN -1);
結 果: 32767 (Bug!)
ソース: printf("%d\n", SHRT_MAX);
結 果: 32767 (OK!)
ソース: printf("%d\n", SHRT_MAX +1);
結 果: -32768 (Bug!)
ソース: printf("%ld\n", LONG_MIN);
結 果: -2147483648 (OK!)
ソース: printf("%ld\n", LONG_MIN -1);
結 果: 2147483647 (Bug!)
ソース: printf("%ld\n", LONG_MAX);
結 果: 2147483647 (OK!)
ソース: printf("%ld\n", LONG_MAX + 1);
結 果: -2147483648 (Bug!)
上記の文が画面に表示されるはずです。これは、あくまでも一つの例で、処理系によっては、値が変わってきます。
2組の printf( ) 文は、上の方が、Cのソースコードを表示させるもので、下の方がその結果をあらわしたものです。
ソースコード中のコメントにも書きましたが、'%' を表示させるには '%%' と記述するので、'%%d' で '%d' と表示されます。
'\' を表示させるには '\\' と記述するので、'\\n' で \n と表示されます。
ダブルコーテイション( " )を表示するには、'\"' と記述します。このような手はずで、ソースコードを画面に表示しています。
#include <stdio.h>
#include <limits.h>
void main(void);
void main(void)
{
こういった文も全て fprintf( ) で、ファイルに出力するプログラムを作れば、そのプログラムの実行結果をもう一度コンパイルして、実行できます (^^)。 */
#include <stdio.h>
#include <limits.h> /* 文字定数を使う */
void main(void);
void main(void)
{
/* \" : " と表示される
%%d : %d と表示される
\\n : \n と表示される */
printf("ソース: printf(\"%%d\\n\", SCHAR_MIN );\n");
printf("結 果: %d (OK!)\n", SCHAR_MIN);
printf("ソース: printf(\"%%d\\n\", SCHAR_MAX);\n");
printf("結 果: %d (OK!)\n", SCHAR_MAX);
printf("ソース: printf(\"%%d\\n\", SHRT_MIN);\n");
printf("結 果: %d (OK!)\n", SHRT_MIN);
printf("ソース: printf(\"%%d\\n\", SHRT_MIN -1);\n");
printf("結 果: %d (Bug!)\n", SHRT_MIN -1);
printf("ソース: printf(\"%%d\\n\", SHRT_MAX);\n");
printf("結 果: %d (OK!)\n", SHRT_MAX);
printf("ソース: printf(\"%%d\\n\", SHRT_MAX +1);\n");
printf("結 果: %d (Bug!)\n", SHRT_MAX +1);
printf("ソース: printf(\"%%ld\\n\", LONG_MIN);\n");
printf("結 果: %ld (OK!)\n", LONG_MIN);
printf("ソース: printf(\"%%ld\\n\", LONG_MIN -1);\n");
printf("結 果: %ld (Bug!)\n", LONG_MIN -1);
printf("ソース: printf(\"%%ld\\n\", LONG_MAX);\n");
printf("結 果: %ld (OK!)\n", LONG_MAX);
printf("ソース: printf(\"%%ld\\n\", LONG_MAX + 1);\n");
printf("結 果: %ld (Bug!)\n", LONG_MAX + 1);
}
|
/* 処理系によっては、最小値より、1 小さい値を正常に表示するものもあります。
printf("%d\n", CHAR_MIN -1);
printf("%d\n", CHAR_MAX + 1);
上記のコードは正常に動作します。書式指定子 %d で表示できる範囲は、INT_MIN から INT_MAX の間 ( -32768 から +32767 の範囲 )だからです。
変数は、その値の取り得る範囲を熟考してから、型を決めなければなりません。一例を下記に示します。
c = getchar( );
c には文字が入るので、c は char 型かというと、getchar( ) は入力に失敗すると、EOF ( -1 ) を返すので、int 型でなければなりません。 */
[整数の内部表現]←このソース→[NDEBUGマクロとassert( )]
/* (C) 2000- YFプロ. All Rights Reserved. */ 提供:C言語講座−それ自体コンパイルできる教材を使った講座です−