サイトマップ / C言語講座出入り口総目次目次:バグ対策>整数の取り得る範囲

青い直線

整数の取り得る範囲

青い直線

[整数の内部表現]←このソース→[NDEBUGマクロとassert( )]

/* limits.h の中の記号定数 */

/* 今日は、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言語講座−それ自体コンパイルできる教材を使った講座です−

青い直線

サイトマップ / C言語講座出入り口総目次目次:バグ対策>整数の取り得る範囲