
C言語のきほん|プログラミングで使う進数の基本
数字の見え方が変わると、C言語の理解がぐっと深まる。2進数・8進数・16進数をやさしく整理しよう。
C言語を学んでいると、普段の生活ではあまり見かけない数字の表記が出てきます。
それが 2進数、8進数、16進数 です。
最初は少し難しく感じやすいところですが、ここはとても大切な基礎です。
なぜなら、コンピュータの内部ではデータを 0 と 1 で扱っていて、その世界とC言語のコードがつながっているからです。
特にC言語では、メモリの内容、ビット演算、文字コード、機器制御などで 16進数 がよく登場します。
8進数は昔ほど登場頻度は高くありませんが、C言語の整数定数のルールとして知っておくと安心です。
ここでは、10進数との違い、変換の考え方、C言語での書き方まで、順番にやさしく解説していきます。
数字が苦手でも大丈夫です。表や図のイメージで理解できるように、丁寧に整理していきましょう。
進数とは何か
私たちが普段使っている数は 10進数 です。
0 から 9 までの10種類の数字を使って数を表します。
一方、プログラミングでは用途に応じて別の進数も使います。
| 進数 | 使う数字 | 特徴 |
|---|---|---|
| 10進数 | 0~9 | 普段の生活で使う表記 |
| 2進数 | 0, 1 | コンピュータ内部の基本表現 |
| 8進数 | 0~7 | 2進数を3桁ごとにまとめやすい |
| 16進数 | 0~9, A~F | 2進数を4桁ごとにまとめやすい |
ここで大事なのは、同じ値でも表記のしかたが違うだけ ということです。
たとえば 10進数の 123 は、2進数や16進数で表すこともできます。
2進数の基本
2進数は、0 と 1 の2つだけで数を表す方法です。
コンピュータは電気的な ON / OFF の2状態をもとに動いているため、内部ではこの 2進数 が基本になります。
たとえば、10進数の 5 は 2進数では 101 です。
101(2) = 1×2² + 0×2¹ + 1×2⁰ = 4 + 0 + 1 = 5
2進数は右端から順に、1、2、4、8、16… という重みを持っています。
この考え方がわかると、変換の仕組みも理解しやすくなります。
C言語でのポイント
学習の基本としては、C言語では 2進数をそのまま整数定数として書く場面はあまり使わない、と覚えておくとよいです。
その代わり、2進数の考え方を理解して、実際のコードでは10進数や16進数で書く という場面が多いです。
8進数の基本
8進数は、0 から 7 までを使って数を表す方法です。
2進数を 3桁ずつ まとめると対応しやすいため、昔から使われてきました。
C言語では、整数定数の先頭に 0 を付けると 8進数として扱われます。
例:
- 0173
この書き方は便利ですが、初心者のうちは見落としやすいポイントでもあります。
たとえば 0123 は、見た目は 123 に似ていますが、C言語では 8進数です。
16進数の基本
16進数は、0~9 に加えて A~F を使って数を表します。
- A は 10
- B は 11
- C は 12
- D は 13
- E は 14
- F は 15
C言語では、先頭に 0x または 0X を付けると 16進数になります。
例:
- 0x7B
- 0X7B
16進数がよく使われる理由は、2進数との相性がとてもよいからです。
2進数4桁が16進数1桁に対応するので、長い2進数を短く読みやすく書けます。
1111 0110(2) → F6(16)
この対応は、メモリの値やビット列を扱うときにとても便利です。
10進数 123 を変換してみよう
ここからは、10進数の 123 を例にして、2進数、8進数、16進数のつながりを見ていきます。
1つの数字を別の表し方で見られるようになると、進数の理解が一気に進みます。
10進数から2進数への変換
10進数を2進数に変換するときは、2で割って余りを逆順に並べる方法を使います。
手順
- 数を 2 で割る
- 商と余りを記録する
- 商が 0 になるまで繰り返す
- 余りを下から上に読む
123 の変換例

2進数から8進数への変換
2進数から8進数に変換するときは、右から3桁ずつ区切る のがコツです。
8 は 2³ なので、2進数3桁と8進数1桁が対応します。
123 の2進数 1111011 を使ってみます。
3桁ずつ区切る
1 111 011
先頭をそろえるために 0 を補うと、さらに見やすくなります。
001 111 011
各ブロックを数値に直す
- 001 は 1
- 111 は 7
- 011 は 3
つまり、
123(10) = 173(8)
このように、8進数は 2進数を3桁ごとにまとめて読める表記だと考えると理解しやすいです。
2進数から16進数への変換
2進数から16進数に変換するときは、右から4桁ずつ区切る のがポイントです。
16 は 2⁴ なので、2進数4桁と16進数1桁が対応します。
同じく 1111011 を使います。
4桁ずつ区切る
111 1011
先頭を 0 で補うと、
0111 1011
各ブロックを16進数に直す
- 0111 は 7
- 1011 は 11 なので B
したがって、
123(10) = 7B(16)
16進数の便利さはここにあります。
2進数だと長く見える数でも、16進数にするとかなり読みやすくなります。
変換の流れを図で整理する
ここまでの流れを、1つの図としてまとめるとこんなイメージです。

4ビットと16進数の対応表
4桁の2進数と1桁の16進数の対応は、C言語ではとても重要です。
ここは毎回計算するより、表を見ながら少しずつ覚えていくのがおすすめです。
| 10進数 | 2進数 | 16進数 |
|---|---|---|
| 0 | 0000 | 0 |
| 1 | 0001 | 1 |
| 2 | 0010 | 2 |
| 3 | 0011 | 3 |
| 4 | 0100 | 4 |
| 5 | 0101 | 5 |
| 6 | 0110 | 6 |
| 7 | 0111 | 7 |
| 8 | 1000 | 8 |
| 9 | 1001 | 9 |
| 10 | 1010 | A |
| 11 | 1011 | B |
| 12 | 1100 | C |
| 13 | 1101 | D |
| 14 | 1110 | E |
| 15 | 1111 | F |
特によく出てくるのはこのあたりです。
- 1010 = A
- 1011 = B
- 1111 = F
- 11111111 = FF
この対応がスムーズに読めるようになると、ビット操作やメモリの値を扱う場面でかなり強くなれます。
C言語での書き方
C言語では、同じ値でも表記のしかたを変えられます。
整数定数として書くときのルールを整理しておきましょう。
| 表記 | 意味 | 例 |
|---|---|---|
| 123 | 10進数 | 123 |
| 0173 | 8進数 | 10進数で123 |
| 0x7B | 16進数 | 10進数で123 |
ここで特に注意したいのが、先頭の 0 です。
- 123 は10進数
- 0123 は8進数
この違いは、C言語ではとても大事です。
コードを書くときも読むときも、先頭の 0 の有無は必ず意識しておきましょう。
サンプルプログラムで確認する
ファイル名:4_6_1.c
#include <stdio.h>
int main(void)
{
/* 同じ値を10進数、8進数、16進数で表す */
int decimal_value = 123;
int octal_value = 0173;
int hex_value = 0x7B;
/* 10進数として表示して比較する */
printf("10進数の 123 は: %d\n", decimal_value);
printf("8進数の 0173 を10進数で表示すると: %d\n", octal_value);
printf("16進数の 0x7B を10進数で表示すると: %d\n", hex_value);
/* 16進数として表示する例 */
printf("10進数の 123 を16進数で表示すると: %X\n", decimal_value);
return 0;
}実行結果例
10進数の 123 は: 123
8進数の 0173 を10進数で表示すると: 123
16進数の 0x7B を10進数で表示すると: 123
10進数の 123 を16進数で表示すると: 7Bサンプルプログラムの解説
同じ値を別の表記で書いている
int decimal_value = 123;
int octal_value = 0173;
int hex_value = 0x7B;この3つは、見た目は違ってもすべて同じ値を表しています。
C言語では、値そのものと、どう表記するかは分けて考えることが大切です。
ここが理解できると、コード中に 0xFF や 077 のような数字が出てきても、落ち着いて読めるようになります。
printf で表示形式を変える
printf("10進数の 123 を16進数で表示すると: %X\n", decimal_value);ここでは %X を使って、10進数の値を16進数として表示しています。
表示形式を変えるだけで、同じ値を別の見え方で確認できるのがポイントです。
よく使う表示指定子は次のようなイメージです。
| 書式指定子 | 表示のしかた |
|---|---|
| %d | 10進数で表示 |
| %o | 8進数で表示 |
| %x | 16進数で表示(a~fは小文字) |
| %X | 16進数で表示(A~Fは大文字) |
たとえば、decimal_value を %o で表示すれば 173、%X で表示すれば 7B と表示されます。
よくつまずきやすいポイント
先頭の 0 を見落とす
これはC言語で本当によくあるポイントです。
int n = 0123;この値は 10進数の123ではありません。
先頭に 0 があるので 8進数として解釈され、10進数では 83 になります。
逆に、10進数の123を入れたいならこう書きます。
int n = 123;見た目が似ているので、慣れるまでは注意して見ていくのがおすすめです。
16進数の A~F は数字の続き
16進数の A~F は、文字に見えますが意味としては数字です。
- A = 10
- B = 11
- C = 12
- D = 13
- E = 14
- F = 15
最初は少し違和感がありますが、16進数では自然なルールです。
英字が出てきても、数字の一部として読むクセをつけるとスムーズになります。
2進数は書かなくても理解は必要
C言語のコードで2進数を直接書かない場面でも、2進数の考え方はとても大事です。
特にビット演算やフラグ処理では、16進数を見て2進数の形をイメージできると理解が一気に進みます。
たとえば、
0x0F = 00001111
0xF0 = 11110000
このような対応が頭に浮かぶと、AND や OR の動きも読みやすくなります。
覚え方のコツ
進数の学習は、最初から全部を完璧に計算しようとしなくて大丈夫です。
むしろ、対応関係を見ながら慣れていくほうがスムーズです。
2進数と16進数の対応を優先する
まずは 4ビット と 16進数1桁 の対応を少しずつ覚えるのがおすすめです。
ここがわかると、実際のコードを読む力がぐっと上がります。
8進数は 3桁区切り のルールだけでも十分役立つ
8進数は使用頻度はやや低めですが、C言語の整数定数として出てくることがあります。
2進数を3桁ずつ区切る、というルールを覚えておくだけでもかなり助かります。
同じ値をいろいろな表記で見てみる
たとえば 15 や 31 のような小さめの数字で、10進数、2進数、8進数、16進数を対応させてみると感覚がつかみやすいです。
15(10) = 1111(2) = 17(8) = F(16)
31(10) = 11111(2) = 37(8) = 1F(16)
こうした小さな練習を積み重ねると、数字の見え方が自然につながっていきます。
