C言語を習得する上で、最も根幹となる概念の一つがデータ型です。
C言語は静的型付け言語であり、変数を宣言する際には必ずその変数がどのような種類のデータを扱うかを指定しなければなりません。
型を正しく理解することは、メモリ効率の良いプログラムを書くだけでなく、バグの少ない安全なコードを記述するために不可欠です。
本記事では、基本型から派生型、さらにはモダンなC言語で推奨される固定幅整数型まで、データ型に関する情報を網羅的に解説します。
C言語におけるデータ型の役割
C言語においてデータ型を定義することは、コンピュータに対して「そのデータのために何バイトのメモリを確保し、どのような形式で解釈するか」を指示することを意味します。
例えば、同じ 4 バイトのデータであっても、それを整数として扱うのか、浮動小数点数として扱うのかによって、コンピュータ内部でのビットパターンの解釈は全く異なります。
また、C言語はハードウェアに近いレイヤーを扱う言語であるため、ターゲットとなる CPU アーキテクチャ (32bit や 64bit) によって型のサイズが変動する場合があるという特徴があります。
この記事を通じて、各型の特性と適切な使い分けをマスターしましょう。
基本的なデータ型一覧 (整数・浮動小数点数・文字)
まずは、C言語で最も頻繁に使用される基本的なデータ型について解説します。
これらは「算術型」とも呼ばれ、数値や文字を保持するために使用されます。
整数型 (Integer Types)
整数型は、小数点を含まない数値を扱うための型です。
符号付き (signed) と符号なし (unsigned) の 2 種類があり、デフォルトでは符号付きとして扱われます。
| 型名 | サイズ (目安) | 範囲 (符号付きの場合) | 書式指定子 |
|---|---|---|---|
char | 1 byte | -128 ~ 127 | %c, %d |
short | 2 byte | -32,768 ~ 32,767 | %hd |
int | 4 byte | -2,147,483,648 ~ 2,147,483,647 | %d |
long | 4 or 8 byte | システムに依存 | %ld |
long long | 8 byte | -9.22e18 ~ 9.22e18 | %lld |
C言語の規格上、int 型のサイズは「16ビット以上」と定められていますが、現代の主要な環境 (Windows, Linux, macOS) では4バイト (32ビット)として実装されていることが一般的です。
しかし、組み込みシステムなどでは 2 バイトとして扱われることもあるため、環境依存であることを意識する必要があります。
浮動小数点型 (Floating-Point Types)
小数を扱うための型です。
精度によって 3 つのレベルに分かれています。
| 型名 | サイズ | 有効桁数 (目安) | 書式指定子 |
|---|---|---|---|
float | 4 byte | 約 7 桁 | %f |
double | 8 byte | 約 15 桁 | %lf, %f |
long double | 12 or 16 byte | 約 18 桁以上 | %Lf |
一般的には、精度のバランスが良い double 型 が最も多用されます。
float 型はメモリ消費を抑えたい場合や、GPU 計算のように大量のデータを高速に処理する必要がある場合に使用されます。
文字型 (Character Type)
char 型は 1 バイトの整数型ですが、主に文字を扱うために利用されます。
C言語では、文字は内部的に ASCII コード などの数値として保持されます。
char alphabet = 'A'; // 内部的には 65 という数値
固定幅整数型 (stdint.h)
前述の通り、int や long のサイズはプラットフォームによって変動します。
これにより、ある環境で動作していたコードが別の環境でオーバーフローを起こすといった問題が発生しやすくなります。
この問題を解決するために導入されたのが、stdint.h ヘッダーで定義されている固定幅整数型です。
現代的な C 言語プログラミングにおいては、サイズを明示するためにこれらの型を使用することが強く推奨されます。
| 型名 | 意味 | ビット数 | 範囲 |
|---|---|---|---|
int8_t | 符号あり 8bit 整数 | 8 bit | -128 ~ 127 |
uint8_t | 符号なし 8bit 整数 | 8 bit | 0 ~ 255 |
int16_t | 符号あり 16bit 整数 | 16 bit | -32,768 ~ 32,767 |
uint16_t | 符号なし 16bit 整数 | 16 bit | 0 ~ 65,535 |
int32_t | 符号あり 32bit 整数 | 32 bit | 約 -21億 ~ 21億 |
uint32_t | 符号なし 32bit 整数 | 32 bit | 0 ~ 約 42億 |
int64_t | 符号あり 64bit 整数 | 64 bit | 膨大な範囲 |
uint64_t | 符号なし 64bit 整数 | 64 bit | 0 ~ 1.84e19 |
これらの型を使用することで、コードの移植性 (ポータビリティ) が大幅に向上します。
例えば、通信プロトコルの実装やバイナリファイルの読み書きなど、データのサイズが厳密に決まっている場面では必須の知識となります。
特殊な型:void 型と bool 型
C言語には、数値や文字以外を扱うための特殊な型も存在します。
void 型
void 型は「型がないこと」を意味します。
主に以下の 3 つの用途で使用されます。
- 関数の戻り値がないことを示す:
void functionName(void); - 関数の引数がないことを明示する:
int main(void) - 汎用ポインタ:
void *ptr;(任意の型のメモリアドレスを保持できる)
bool 型 (stdbool.h)
古い C 言語 (C89/90) には真偽値を表す専用の型がありませんでしたが、C99 規格以降では stdbool.h をインクルードすることで bool 型が使用可能になりました。
true:内部的には 1false:内部的には 0
条件分岐のフラグなどで、整数型の 0 や 1 を直接使うよりもコードの意図が明確になります。
派生型 (ポインタ・配列・構造体)
基本型を組み合わせて作られる「派生型」についても触れておきましょう。
ポインタ型
特定の型が格納されている「メモリのアドレス」を扱うための型です。
int *p; のように記述し、変数 p は int 型データの場所を指し示します。
C言語の強力さの源であり、同時に学習者が最も躓きやすいポイントでもあります。
配列型
同じ型のデータを連続してメモリ上に並べたものです。
int scores[5]; と宣言すれば、整数 5 個分の領域が確保されます。
構造体 (struct)
異なる型をひとまとめにして、新しいデータ型を定義する機能です。
例えば、「学生」というデータ型を作る場合、名前 (文字列) や年齢 (整数) を一つの構造体にまとめることができます。
struct Student {
char name[50];
int age;
double score;
};
型のサイズを確認する方法:sizeof 演算子
自分のプログラムが実行されている環境で、各型が具体的に何バイト消費しているかを知るには sizeof 演算子を使用します。
#include <stdio.h>
int main(void) {
printf("int型のサイズ: %zu バイト\n", sizeof(int));
printf("double型のサイズ: %zu バイト\n", sizeof(double));
return 0;
}
sizeof はバイト数を size_t という符号なし整数型で返します。
そのため、printf で表示する際の書式指定子には %zu を使用するのが正解です。
型変換 (キャスト) の重要性
プログラムを組んでいると、異なる型の間で計算を行いたい場面が出てきます。
C言語には、自動的に行われる「暗黙的な型変換」と、プログラマが明示的に行う「明示的な型変換 (キャスト)」があります。
暗黙的な型変換 (型昇格)
例えば、int と double の計算を行うと、結果は精度の高い double に合わせられます。
int a = 5;
double b = 2.0;
double result = a / b; // a が double に変換されてから計算される
キャスト演算子
意図的に型を変えたい場合は、(型名)変数名 という書式を使います。
特に整数同士の割り算で小数を求めたい場合に重要です。
int x = 5;
int y = 2;
double div = (double)x / y; // 2.5 が得られる。キャストしないと 2 になる。
不適切な型変換はデータの欠損や意図しない動作の原因となるため、特に大きな型から小さな型へ変換する際は注意が必要です。
書式指定子の一覧まとめ
printf や scanf でデータを出力・入力する際には、その型に対応した「書式指定子」を正しく指定する必要があります。
| 型 | 書式指定子 (printf) | 備考 |
|---|---|---|
char | %c | 1文字として表示 |
int | %d | 10進数整数 |
unsigned int | %u | 符号なし10進数 |
short | %hd | 短精度整数 |
long | %ld | 長精度整数 |
long long | %lld | さらに長い整数 |
float | %f | 実数 (小数点) |
double | %f または %lf | scanf では %lf が必須 |
char[] (文字列) | %s | null終端文字列 |
void * (ポインタ) | %p | アドレスを16進数で表示 |
size_t | %zu | sizeof の結果など |
書式指定子を間違えると、メモリの内容が正しく解釈されず、デバッグの難しいバグを引き起こします。
まとめ
C言語のデータ型は、単なるデータの分類以上の意味を持っています。
それは、限られた計算資源である「メモリ」と「CPU」をいかに効率よく、かつ正確に扱うかという設計思想そのものです。
本記事で紹介した内容のポイントを振り返ります。
- 基本型:
int,char,float,doubleなど、数値や文字の基本単位。 - 環境依存性:型のサイズは環境によって変わるため、
sizeofで確認することが重要。 - 固定幅整数型:移植性を高めるために
stdint.hのint32_tなどを活用する。 - 書式指定子:入出力時には型に合った指定子を正しく使う。
- 型変換:意図しないデータ欠損を防ぐため、キャストの仕組みを理解する。
データ型を正しく選択できるようになると、プログラムのパフォーマンスは向上し、予期せぬ動作を未然に防ぐことができます。
これから C 言語で複雑なアルゴリズムやシステムを構築していく際、この基礎知識が必ずあなたを助けてくれるはずです。
まずは各型のサイズや範囲を意識しながら、実際にコードを書いてその挙動を確かめてみてください。






