先頭へ戻る

数の表現方法 | Programming Place Plus C言語編 第18章

Programming Place Plus トップページC言語編

先頭へ戻る

この章の概要

この章の概要です。


8進数

プログラミングでは、普段の生活で使っている 10進数のほか、2進数や 8進数、16進数を使う機会があります。

この章では、C言語での事情に限定した話をします。もし、こういった数の表現に馴染みがない場合は、まず先に、「コンピュータサイエンス編基数」のページをお読みください。

まず、8進数を取り上げます。

C言語のソースコード上では、数値の先頭に「0」を付加すると、その数値を 8進数とみなすことになっています。たとえば、「0100」は、8進数の 100 のことです。浮動小数点数を 8進法では表記できません。

まれに、この表記方法があることを知らなかったり忘れていたりして、ソースコード上の単なる桁数合わせのような感覚で、先頭に 0 を付けてしまうバグを見かけることがあります。「100」のつもりで「0100」と書くと、違う数になってしまうので注意が必要です。

printf関数scanf関数sscanf関数は、8進数での入出力にも対応しています。8進数を扱うには、“%o” という変換指定子を使います。ただし、“%o” は負数を扱えません

たとえば、printf関数で “%o” を試してみます。

#include <stdio.h>

int main(void)
{
    printf("%o\n", 0100);
    printf("%o\n",  100);
    printf("%d\n", 0100);
    printf("%d\n",  100);

    return 0;
}

実行結果:

100
144
64
100

ソースコード上の数の表記が何進法であるかと、printf関数の変換指定子を何にするかは対応するわけではありません。ソースコード上では 8進法を使っていても、10進法で表記した出力結果が欲しいのなら “%d” 変換指定子を使います。

また、ソースコード上で「64」と書いても、「0100」と書いても、それは同じ数であることをよく理解してください。異なるのは表記方法であって、数値が違っているのではありません。

“%o” 変換指定子による出力結果の方には、数の先頭に「0」が付加されていません。もし、「0」を付けて欲しいのであれば、変換フラグと呼ばれる文字を付け足して、“#o” という変換を指定します。

#include <stdio.h>

int main(void)
{
    printf("%#o\n", 0100);

    return 0;
}

実行結果:

0100

16進数

C言語のソースコード上では、数値の先頭に「0x」または「0X」を付加すると、その数値を 16進数とみなすことになっています。たとえば、「0x100」は、16進数の 100 のことです。

浮動小数点数の場合にも 16進数による表記が行えますが、これは記法が特殊なので、第20章で改めて取り上げることにします。

printf関数は、16進数での入出力にも対応しています。16進数を扱うには、“%x” または “%X” という変換指定子を使います。“%x” の場合は「A~F」を小文字で出力し、“%X” の場合は大文字で出力します。なお、“%x” や “%X” は負数を扱えません

同様に、scanf関数sscanf関数でも、“%x” や “%X” を使います。こちらは、“%x” と “%X” には違いがなく、「A~F」でも「a~f」でも受け付けてくれます。入力の場合は、区別を付けない方が使いやすいはずです。

printf関数で “%x” と “%X” を試してみます。

#include <stdio.h>

int main(void)
{
    printf("%x\n", 0x1f);
    printf("%x\n", 0x1F);
    printf("%X\n", 0x1f);
    printf("%X\n", 0x1F);

    return 0;
}

実行結果:

1f
1f
1F
1F


sizeof演算子

sizeof演算子を使うと、型の大きさを知ることができます。

型の大きさはバイト単位で表現されますから、大きさが分かれば、その型で表現できる数の範囲も分かります。

sizeof演算子は、以下のいずれかの構文で使用します。

sizeof(型名)
sizeof()
sizeof

型に応じた大きさ、あるいは式の結果の型の大きさがバイト単位で得られます。型名を指定する場合は ( ) で囲まないといけません。式の場合でも、( ) で囲む方が一般的かと思います。

具体的なコードは次のようになります。

int main(void)
{
    size_t a;
    a = sizeof(int);

    int num = 0;
    a = sizeof(num);
    a = sizeof num;    // 上の行と同じ意味

    return 0;
}

sizeof演算子に与える式の部分は、ごくわずかな例外的な場面を除いて、実行されません。たとえば、「sizeof(func())」のように使用したとしても、func関数が呼び出されることはありません。

【上級】ごくわずかな例外的な場面は、可変長配列(第25章)を与えた場合です。このときは、式が評価(第27章)されます。

【上級】そもそも、関数を与えるような使い方はまずしませんが、この場合は戻り値の型の大きさが得られます。もし、戻り値の型が void の場合はコンパイルエラーになります。

sizeof演算子で得られる値は、size_t型の定数です。定数なので、コンパイルした時点で、何らかの整数値が得られています。

size_t型は、標準ライブラリの中で定義されているため、使用するためには #include で取り込む必要があります。<stddef.h> をはじめとして、いくつかの標準ヘッダで定義されており、<stdio.h> にも定義されているため、大抵はあまり意識せずに使用できます。

【上級】size_t型は整数を扱う型ですが、C言語に組み込まれている標準的な型ではなく、typedef(第26章)という機能によって作られた、型の別名に過ぎません。

試しに、int型の大きさを出力してみましょう。

#include <stdio.h>

int main(void)
{
    printf( "int型の大きさは %zuByte\n", sizeof(int) );

    return 0;
}

実行結果:

int型の大きさは 4Byte

printf関数や scanf関数で size_t型の値を扱う際には、“%zu” という変換指定を使います。

“%zu” は C99規格で追加されました。これが使えない場合は、“%lu” などで代替します

このサンプルプログラムを実行した環境では、int型の大きさが 4バイトだという結果が出ましたが、ほかの環境では結果が異なるかもしれません。

int型の大きさと表現範囲

先ほどのサンプルプログラムでは、int型の大きさは 4バイトになりましたが、int型の大きさは明確に定められてはおらず、処理系によって異なります

明確に決められていることは、-32767~32767 の範囲の値を表現できるだけの大きさがあるという点だけです。この範囲を表現するためには 16ビット必要なので、実質的に、int型は 16ビットよりは大きいことが保証されます。

もし、int型が 4バイト(32ビット)であれば、表現できる値の範囲はどのくらいになるでしょうか?

まず、int型は負数も扱えます。負数の表現には、2の補数表現を使うと仮定すると(この仮定はほとんど確実に正しいです)、最上位ビットは符号の表現に使わなければなりませんから、231 で表現できる数が最大値です。計算すると、最大値は +2,147,483,647 であることが分かります。

最小値の方は、2の補数表現では、正の側よりも 1つ多く表現できるので -2,147,483,648 です。ただし、C言語では、2の補数表現を使うことが強制されているわけではないので、確実に表現できる最小値は -2,147,483,647 です。

よって、32ビットの int型で確実に表現できる値の範囲は、-2,147,483,647~+2,147,483,647 です。

より直接的に限界値を調べる方法を、第19章で後で取り上げます


練習問題

問題① 標準入力から 16進数の整数を受け取り、それを 8進数で出力するプログラムを作成してください。

問題② 8・10・16進数の対応表を表示するプログラムを作ってください。値の範囲は、10進数で「0~16」とします。

問題③ 次の式を手作業で計算してみてください。そして、答えを確認するためのプログラムを作成してください。
「0x3c5 × 26 - 0741」は 10進数でいくつ?

問題④ 2進数の 0111101 を 10進数と 16進数に変換してください。


解答ページはこちら

参考リンク


更新履歴

’2018/6/6 全体的に構成と内容を修正。
2進数の負の整数」の項を追加。
参考書籍を追加。

’2018/6/5 第19章から移動してくる形で新規作成。



前の章へ (第17章 処理の流れを制御する)

次の章へ (第19章 整数型)

C言語編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
Twitter でツイート Twitter をフォロー LINE で送る
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー