第13章 データ型の修飾

データ型については第2章で説明しましたが、この章では、データ型の修飾について説明します。

1. 型のサイズ修飾

既に学習した「long」はサイズを修飾するものです。 実は「long」は「long int」を略した記述で、その意味は「int型と同じかそれより大きい」となります。同様に「int型と同じかそれより小さい」を表す「short」(short int の略)も存在します。

C言語の規格では整数型のサイズは処理系に任されており、以下のようにのみ規定しています。

(整数型)
short int ≦ int ≦ long int ≦ long long int

  • short int は short と記述可能
  • long int は long と記述可能
  • long long int は long long と記述可能

(浮動小数点型)
float ≦ double ≦ long double

バイト幅は処理系により異なり、共通サイズのデータ型は 1バイト幅の「char型」だけです。

特に「int型」は「対象となっているマシン環境で、最も効率よく処理できる整数幅を int型に割り当てる」とことになっており、処理系によって異なります。

このBlogでは、主にWindows系のC言語で用いられている「int幅 = 4バイト」を採用しています。その他の処理系のC言語を利用している人は、自分の環境に合わせて読みかえるようにしてください。

2. 型の符号修飾

short や int などの整数型の変数は、符号修飾をすることができます。

単に「short」や「int」としたときは
「符号つき…負の値も扱える」 です。

これは、「符号つき…負の値も扱える」という修飾 「signed」を付けて、「signed short」や「signed int」とすべきところを「signed」を省略して単に「short」や「int」とした場合です。

これに対し、「unsigned」をつけて「unsigned short」や「unsigned int」とした場合には
符号なし…正の値のみを扱う」 となります。

「unsigned」を用いると、符号ビットを数値として使うため、扱える数値の範囲が倍になります。 このため、unsigned は「負数は必要ない。その代わり正数をもっと表現したい。」という場合に用います。

※ 単にcharとした場合、符号つきか符号なしかは処理系に任されます。

3. 宣言の順番

変数の宣言は基本的には、

記憶クラス 型修飾子(符号修飾子、サイズ修飾子) データ型 変数名;

という順番で行います。このとき、水色部分は省略ができます。

【整数型の場合】
記憶クラス符号修飾子サイズ修飾子基本型指定
auto
static
signed
unsigned
short
long
long long
int
  • 記憶クラスの「auto」と「static」については「第12章の1 記憶クラスの種類」を参照してください。
  • また、記憶クラスの「register」と「extern」はこのBlogでは扱いません。
【浮動小数点型の場合】
記憶クラスサイズ修飾子基本型指定
auto
static
float
long double

4. 整数型のサイズと範囲を表示するプログラム

整数型の最大値と最小値はlimits.hヘッダファイルにマクロ定義されています。また、sizeof演算子を使うと、型の大きさを調べることができます。

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

int main(void)
{
    printf("char           : %d ~ %d\n", CHAR_MIN, CHAR_MAX);
    printf("signed char    : %d ~ %d\n", SCHAR_MIN, SCHAR_MAX);
    printf("unsigned char  : 0 ~ %u\n", UCHAR_MAX);
    printf("short          : %hd ~ %hd\n", SHRT_MIN, SHRT_MAX);
    printf("unsigned short : 0 ~ %hu\n", USHRT_MAX);
    printf("int            : %d ~ %d\n", INT_MIN, INT_MAX);
    printf("unsigned       : 0 ~ %u\n", UINT_MAX);
    printf("long           : %ld ~ %ld\n", LONG_MIN, LONG_MAX);
    printf("unsigned long  : 0 ~ %lu\n", ULONG_MAX);
    printf("long long           : %lld ~ %lld\n", LLONG_MIN, LLONG_MAX);
    printf("unsigned long long  : 0 ~ %llu\n", ULLONG_MAX);

    printf("charのサイズ      = %zuバイト\n", sizeof(char));
    printf("shortのサイズ     = %zuバイト\n", sizeof(short));
    printf("intのサイズ       = %zuバイト\n", sizeof(int));
    printf("longのサイズ      = %zuバイト\n", sizeof(long));
    printf("long longのサイズ = %zuバイト\n", sizeof(long long));

    return 0;
}

char : 0 ~ 255 signed char : -128 ~ 127 unsigned char : 0 ~ 255 short : -32768 ~ 32767 unsigned short : 0 ~ 65535 int : -2147483648 ~ 2147483647 unsigned : 0 ~ 4294967295 long : -9223372036854775808 ~ 9223372036854775807 unsigned long : 0 ~ 18446744073709551615 long long : -9223372036854775808 ~ 9223372036854775807 unsigned long long : 0 ~ 18446744073709551615 charのサイズ = 1バイト shortのサイズ = 2バイト intのサイズ = 4バイト longのサイズ = 8バイト long longのサイズ = 8バイト

  • 上記の実行結果例はブラウザ上でコードを書いて実行できるサービス「paiza.io」を使って確認しました。
  • C言語の実行環境は「C17 / clang version 10.0.0-4ubuntu1」になります。

5. 浮動小数点型のサイズと範囲を表示するプログラム

float.hヘッダファイルに、それぞれの浮動小数点型が扱える最大値や最小値、および精度がマクロとして定義されています。

#include <stdio.h>
#include <float.h>

int main(void)
{
    printf("float型の最小値       = %e\n", FLT_MIN);
    printf("float型の最大値       = %e\n", FLT_MAX);
    printf("double型の最小値      = %e\n", DBL_MIN);
    printf("double型の最大値      = %e\n", DBL_MAX);
    printf("long double型の最小値 = %Le\n", LDBL_MIN);
    printf("long double型の最大値 = %Le\n\n", LDBL_MAX);

    printf("floatのサイズ       = %zuバイト\n", sizeof(float));
    printf("doubleのサイズ      = %zuバイト\n", sizeof(double));
    printf("long doubleのサイズ = %zuバイト\n\n", sizeof(long double));

    printf("floatの精度       = %d桁\n" ,FLT_DIG);
    printf("doubleの精度      = %d桁\n", DBL_DIG);
    printf("long doubleの精度 = %d桁\n", LDBL_DIG);

    return 0;
}

float型の最小値 = 1.175494e-38 float型の最大値 = 3.402823e+38 double型の最小値 = 2.225074e-308 double型の最大値 = 1.797693e+308 long double型の最小値 = 3.362103e-4932 long double型の最大値 = 1.189731e+4932 floatのサイズ = 4バイト doubleのサイズ = 8バイト long doubleのサイズ = 16バイト floatの精度 = 6桁 doubleの精度 = 15桁 long doubleの精度 = 33桁

上記の実行結果例はブラウザ上でコードを書いて実行できるサービス「paiza.io」を使って確認しました。

  • 上記の実行結果例はブラウザ上でコードを書いて実行できるサービス「paiza.io」を使って確認しました。
  • 精度」は、浮動小数点型のデータが保持できる有効桁数のことを指します。

6. 定数の修飾

第2章の1 定数と変数」で定数の表記方法について扱いましたが、実は定数も接尾語を付加することにより、サイズ修飾と符号修飾が行えるのです。

ここでは、定数のサイズ修飾と符号修飾についてまとめます。

(1) 整数定数の修飾

整数定数をそのまま記述した場合、通常はint型として解釈されます。

接尾語の u または U を 付けるとunsigned型に、接尾語の l (エル)または L を付けるとlong型になります。また、ll(エルエル)またはLLを付けると、long long型になります。

これらの接尾語は同時に付けることも可能で、その順序は問われません。

int n1 = 100;                // そのまま記述するとint型
unsigned n2 = 200U;          // unsigned int型
long n3 = 300L;              // long型
unsigned long n4 = 400UL;    // unsigned long型
long long n5 = 500LL;        // long long型

(2) 浮動小数点定数の修飾

浮動小数点定数をそのまま記述した場合、double型として解釈されます。float型として扱いたい場合には接尾語Fを、long double型として扱いたい場合には接尾語l(エル)またはLを使用します。

double pi = 3.14159;            // そのまま記述するとdouble型  
float x = 2.71828F;             // float型  
long double phi = 1.61803L;     // long double型

コメント