C言語基礎|算術型と基本型

第7章からは、C言語の“型”をちゃんと体系立てて理解していきます。
これまで int と double を中心に進めてきましたが、C言語には「整数っぽい型」「小数っぽい型」だけでもたくさん種類があります。

型の違いが分かるようになると、

  • 変数に入れられる値の範囲がイメージできる。
  • 計算結果がなぜそうなるか(切り捨て・桁落ちなど)を説明できる。
  • printf や scanf の指定(%d や %f など)をミスりにくい。
  • 速度・メモリの使い方も判断できる。

みたいに、プログラムが一気に“安定して書ける”ようになります。

算術型とは何か

C言語で「算術演算(足す・引く・掛ける・割る)ができる型」をまとめて 算術型 と呼びます。
今まで使ってきた int や double も算術型の仲間です。

表:算術演算の例(型が関わるポイント)

演算型が関わる理由
加算a + b結果の型がどうなるかが重要
減算a - b符号付き/符号なしで結果が変わることがある。
乗算a * b桁あふれ(オーバーフロー)しやすい。
除算a / b整数除算か実数除算かで結果が変わる。

この章では、こういう「型による挙動の違い」を、順番にクリアにしていきます。

算術型の分類(全体像)

算術型は、大きく 整数型浮動小数点型 に分かれます。

図:主要な算術型の分類

この図が伝えたいこと

  • 「整数を表す型」がたくさんある(char も整数の仲間)
  • 「実数を表す型」も3種類ある(精度やサイズが違う)
  • enum も整数の一種として扱われる(ただし“基本型”ではない)

整数型(integer type)

整数型は「小数点なしの値」を表します。
さらに中で、文字型int 系型列挙型に分かれます。

整数型の内訳(ざっくり)

種類主な型ざっくり用途ひとこと
文字型char, signed char, unsigned char文字データや小さめ整数文字も内部では数
int 系型short, int, long, long long(signed/unsigned)通常の整数計算一番よく使う
列挙型enum ...決まった選択肢を数で表す意味づけが強い

浮動小数点型(floating type)

浮動小数点型は「小数点を含む実数」を表します。
double をよく使ってきたのは「精度が高くて扱いやすい」からでした。

浮動小数点型のざっくり比較

特徴よくある使いどころ
float比較的軽いが精度は低め大量データでメモリ重視
doubleバランスが良い(よく使う)通常の実数計算全般
long doubleさらに高精度な場合がある精度最優先の計算

基本型(basic type)って何?

ここ、ちょっと用語がややこしいんだけど、イメージはシンプルです。

  • 基本型:キーワードだけで型名が書ける、基本の型たち
    例:int / double / char / long など
  • 基本型ではない算術型:代表が enum(列挙型)

算術型と基本型の関係

呼び名含まれるもの含まれないもの
算術型整数型+浮動小数点型(enum含む)ポインタ型、配列型など
基本型文字型+int系型+浮動小数点型enum

広義の整数と狭義の整数(本書の注意点)

文脈によって「整数型」の指し方がぶれることがあります。

  • 広い意味の整数型:文字型+int系型+列挙型
  • 狭い意味の整数:文字型と列挙型を除いて int 系型だけを指すことがある

ただ、学習中はそこまで神経質にならなくてOK。
まずは「char も整数の仲間」という感覚が持てれば十分です。

サンプルプログラム

ここでは 割り算の結果が型で変わる を短い例で確認します。

プロジェクト名:chap7-1-1 ソースファイル名:chap7-1-1.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

// 算術型の入口:整数除算と実数除算の違いを確認する

#include <stdio.h>

int main(void)
{
    int a = 7;
    int b = 2;

    int    q1 = a / b;                 // 整数除算
    double q2 = (double)a / b;         // 実数除算(型変換してから割る)

    puts("型によって割り算の結果が変わります。");
    printf("a / b を int で受け取ると:%d\n", q1);
    printf("a / b を double で計算すると:%.1f\n", q2);

    return 0;
}

このプログラムで起きていること

行の意図実際に起きることポイント
q1 = a / b7 / 2 は 3 になる整数同士の除算は小数が捨てられる。
q2 = (double)a / b7.0 / 2 で 3.5片方を実数にすると実数除算になる。

登場する命令の書式と役割

#include の書式

  • 書式:#include <stdio.h>
  • 役割:printf や puts などの入出力関数を使うための情報を取り込む

puts の書式

  • 書式:puts(文字列);
  • 役割:文字列を表示して改行する

printf の書式

  • 書式:printf(書式文字列, 値, 値, ...);
  • 役割:書式指定して値を表示する

型変換(キャスト)の書式

  • 書式:(型名)式
  • 役割:計算の途中で型を明示的に変える
    例:(double)a は a を double として扱う、という意味