C言語基礎|文字型

C言語の char は、character(文字)の略で、文字を入れるための型です。
ただしポイントはここで、char は「文字専用の箱」というより、実態としては 小さな整数(1バイト前後)を扱うための型でもあります。

だからこそ、

  • 文字として表示する(A など)
  • 数として扱う(A は 65 など)

この2つが自然に行き来できます。ここが char の面白さであり、最初につまずきやすい所でもあります。

char には3種類ある(そして単なる char は処理系依存)

まず基本はこの3つです。

文字型の種類

ざっくり説明値の範囲のイメージ
char単なる char(符号付きか符号無しかは処理系依存)環境で変わる
signed char符号付き(負もOK)例:-128 ~ 127
unsigned char符号無し(0以上)例:0 ~ 255

ここで大事なのが 単なる char が signed なのか unsigned なのかは環境によって違うこと。
なので「char は必ず 0~255!」みたいに決め打ちしないのが安全です。

単なる char が signed / unsigned どっちかを調べる(<limits.h>)

Cでは <limits.h> に、各型の最小値・最大値が マクロとして用意されています。

char 系の範囲を表すマクロ

マクロ意味
CHAR_MINchar の最小値
CHAR_MAXchar の最大値
SCHAR_MIN / SCHAR_MAXsigned char の最小/最大
UCHAR_MAXunsigned char の最大(最小は0)

そして、単なる char の判定は定番の考え方がこれです。

  • CHAR_MIN が 0 以外(負)なら、char は符号付きの可能性が高い
  • CHAR_MIN が 0 なら、char は符号無しの可能性が高い

サンプルプログラム

単なる char 型が、符号付き型か符号無し型かを判定し、範囲も一緒に表示するプログラムです。

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

// この環境の char が符号付きか符号無しかを調べて、範囲も表示する

#include <stdio.h>
#include <limits.h>

int main(void)
{
    puts("=== char の性質チェック ===");

    printf("char の範囲: %d ~ %d\n", CHAR_MIN, CHAR_MAX);
    printf("signed char の範囲: %d ~ %d\n", SCHAR_MIN, SCHAR_MAX);
    printf("unsigned char の範囲: %u ~ %u\n", 0U, UCHAR_MAX);

    printf("判定: この環境の char は %s として扱われます。\n",
           (CHAR_MIN < 0) ? "符号付き" : "符号無し");

    return 0;
}

登場する命令の書式と「何をするか」

#include

  • 書式:#include <ヘッダ名>
  • 何をする:標準ライブラリやマクロ定義を取り込む
    <stdio.h>:puts / printf を使うため
    <limits.h>:CHAR_MIN などの範囲マクロを使うため

puts

  • 書式:puts(文字列);
  • 何をする:文字列を表示して改行する(見出し表示に便利)

printf

  • 書式:printf(書式文字列, 値, ...);
  • 何をする:値を指定した形式で表示する

条件演算子 ?:

  • 書式:条件 ? 真のときの値 : 偽のときの値
  • 何をする:条件に応じて結果を切り替える(今回だと表示文字列の切替)

char は「小さい整数の箱」でもある

文字として表示するか、数として表示するか

char c = 'A';

%c で表示 → A(文字として表示)
%d で表示 → 65(数として表示:文字コード)

この図が示しているのは、同じ 1バイト程度の値でも、表示の仕方で意味が変わるということです。
Cでは文字は結局「数」として扱えるので、こういう切り替えが自然にできます。

char の範囲が違うと何が困る?

たとえば 200 みたいな値を char に入れたとき、環境によって結果が変わり得ます。

char が signed か unsigned かで起きる違い

入れたい値char が符号無しの場合char が符号付きの場合
100100100
200200負の値になる可能性がある

この表が言いたいのは、char を数として使うときは signed/unsigned の差が効くってことです。
文字コードやバイナリデータを扱うときは、unsigned char を使う場面がよくあります。

補足:文字定数は char 型じゃなくて int 型

'C' や '\n' みたいな 文字定数は、Cでは基本的に int 型です。
でも、代入するときに char に収まる範囲なら問題なく入ります。

文字定数の型と代入の関係

'A' は int 型(文字定数)
↓(代入)
char c に入る(範囲内なのでOK)