変数

C言語も他の言語と同様、変数があります。ここではC言語の変数について見ていきます。


変数の型

C言語で取り扱える変数の型は次の通りです。


型一覧

表記 サイズ 値の範囲 備考
文字型 char 1byte -128 ~ 127
signed char 1byte 「char」又は「unsigned char」と同等
unsigned char 1byte 0 ~ 255
整数型 short(signed short) 2byte -32,768 ~ 32,767
unsigned short 2byte 0 ~ 65,535
int(signed int) 4byte -2,147,483,648 ~ 2,147,483,647 実際はマシンに依存します。32bitの処理系から16bitの処理系に移行するときには注意が必要です。
unsigned int 4byte 0 ~ 4,294,967,295
long(signed long) 4byte -2,147,483,648 ~ 2,147,483,647
unsigned long 4byte 0 ~ 4,294,967,295
浮動小数点型 float 4byte 1.18×10-38 ~ 3.40×1038
double 8byte 2.23×10-308 ~ 1.79×10308
long double 10byte 3.36×10-4932 ~ 1.19×104932
列挙型 enum 不定 不定
構造体 struct 不定 不定
共用体 union 不定 不定
配列 [ ] 不定 不定
ポインタ型 * 不定 不定

データ型のサイズ実測

データ型は処理系に依存しますので、実機にてサイズを確認しておくほうがいいでしょう。

次の関数でサイズを調べる事が出来ます。

sizeof 変数名; 又は sizeof(型名);

それでは実際に実測値を表示させみます。


・ファイル名:sample0201.c

#include <stdio.h>

int main() {
  printf("sizeof(char)           = %d\n",sizeof(char));
  printf("sizeof(signed char)    = %d\n",sizeof(signed char));
  printf("sizeof(unsigned char)  = %d\n",sizeof(unsigned char));
  printf("sizeof(short)          = %d\n",sizeof(short));
  printf("sizeof(unsigned short) = %d\n",sizeof(unsigned short));
  printf("sizeof(int)            = %d\n",sizeof(int));
  printf("sizeof(unsigned int)   = %d\n",sizeof(unsigned int));
  printf("sizeof(long)           = %ld\n",sizeof(long));
  printf("sizeof(unsigned long)  = %ld\n",sizeof(unsigned long));
  printf("sizeof(float)          = %ld\n",sizeof(float));
  printf("sizeof(double)         = %ld\n",sizeof(double));
  printf("sizeof(long double)    = %ld\n",sizeof(long double));

  return 0;
}

・実行結果

C:\dev\c>sample0201 [Enter]
sizeof(char)           = 1
sizeof(signed char)    = 1
sizeof(unsigned char)  = 1
sizeof(short)          = 2
sizeof(unsigned short) = 2
sizeof(int)            = 4
sizeof(unsigned int)   = 4
sizeof(long)           = 4
sizeof(unsigned long)  = 4
sizeof(float)          = 4
sizeof(double)         = 8
sizeof(long double)    = 10
        

▲PageTop

変数の使用

変数を使用するには、次のように宣言します。

データ型 変数名;

また変数を”,”(カンマ)で区切って複数の変数を宣言する事も出来ます。

データ型 変数名1, 変数名2, ・・・;

例えばint型の変数aに10代入する場合はこのようになります。

int a;
a = 10;

また次のように宣言と同時に値の代入(初期化)することも可能です。

int a = 10;

▲PageTop

変数の命名規則

変数名には次の約束があります。

  1. 半角英数字( a ~ z , A ~ Z, _ )のいずれかの文字を使用すること。
  2. 数値を変数名の先頭にする事はできません。
  3. C言語の予約語は変数名にできません。
  4. 大文字と小文字は別物として判断します。

・C言語の予約語(ANSI-1989)

auto       double    int         struct      break       else      long      switch

case       enum      register    typedef     char        extern    return    union

const      float     short       unsigned    continue    for       signed    void

default    goto      sizeof      volatile    do          if        static    while 

※C99では次のキーワードが追加されました。「inline」、「restrict」、「_Bool」、「_Complex」、「_Imaginary」

▲PageTop

型変換

異なった型の変数で演算や代入を行うとき、C言語では自動的に型変換(暗黙の型変換)が行われます。また強制的に型を指定する事も可能で、これを明示的型変換(キャスト)といいます。


暗黙の型変換

暗黙の型変換が行われるのは主に次のような場合です。


1.式内の各オペランドの型が異なるとき。

この場合、一番大きい型に統一されます。このような型変換を「型の昇格」と呼びます。

型の順位は次のようになります。

char < short < int < long < float < double

但し、int型よりも小さい型はすべてint型に統一されます。これを「汎整数拡張」といいます。


2.異なる型へ代入するとき。

この場合は、左辺の型に変換されます。もし左辺の型が右辺より小さいければ情報落ちが発生しますので注意が必要です。


・サンプルソース(sample0202.c)

#include <stdio.h>

int main() {
    float  a = 0.5;
    int    b = 1;
    float  x;
    int    y;
    x = a + b;  /* int bがfloat型に昇格して計算されfloat型xに代入される。 */
    y = a + b;  /* int bがfloat型に昇格して計算されint型yに代入される。 */
    printf("x=%f\n", x);
    printf("y=%d\n", y);

    return 0;
}

・実行結果

C:\dev\c>sample0202 [Enter]
x=1.500000
y=1  ← floatからintに変換され情報落ち(小数点以下が丸められている)が発生。
            

明示的型変換(キャスト)

「キャスト演算子」を使用することで、一時的に型を変換することが出来ます。


・サンプルソース(sample0203.c)

#include <stdio.h>

int main() {
    int    a = 5;
    int    b = 2;
    float  x;
    float  y;
    x = a / b;  /* int型同士の演算なので算出結果もint型になる。 */
    y = (float)a / b;  /* 一方のオペランドをfloat型に「キャスト」する事で式内最大のfloat型に揃えられる。 */
    printf("x=%f\n", x);
    printf("y=%f\n", y);

    return 0;
}

・実行結果

C:\dev\c>sample0203 [Enter]
x=2.000000
y=2.500000
        

その他、関数による型変換

C言語には型変換を行う次の関数が用意されています。


■文字列 → int型
関数名 書式 ヘッダー 引数/戻り値 備考
atoi() int atoi(const char *nptr); <stdlib.h>
【*nptr】
先頭に数値が含まれる文字列。
【戻り値】
変換された数値。失敗時は0。
数値は10進数。

■文字列 → long型
関数名 書式 ヘッダー 引数/戻り値 備考
atol() long atol(const char *nptr); <stdlib.h>
【*nptr】
先頭に数値が含まれる文字列。
【戻り値】
変換された数値。失敗時は0。
数値は10進数。
strtol() long strtol(
 const char *nptr,
 char **endptr,
 int base);
<stdlib.h>
【*nptr】
先頭に数値が含まれる文字列。
【**endptr】
文字列中で変換が終了した位置の文字列を示すポインタ。
【base】
変換する数値の基数。(2~36)
【戻り値】
成功時:
変換された数値。
失敗時:
ULONG_MAX(オーバーフロー)
ULONG_MIN(アンダーフロー)
変換文字列の書式
[空白][符号][0][xまたはX][数値]。

base(基数)が0のときは「変換文字列」から次のように決定します。
  • 01~07のとき8進数。
  • 0xまたは0Xのとき16進数。
  • 1~9のとき10進数。
エラーが発生したとき「errno」(グローバル変数)にERANGEが設定されます。

■文字列 → unsigned long型
関数名 書式 ヘッダー 引数/戻り値 備考
strtoul() unsigned long strtoul(
 const char *nptr,
 char **endptr,
 int base);
<stdlib.h>
【*nptr】
先頭に数値が含まれる文字列。
【**endptr】
文字列中で変換が終了した位置の文字列を示すポインタ。
【base】
変換する数値の基数。(2~36)
【戻り値】
成功時:
変換された数値(変換文字がマイナスのときは符号反転)。
失敗時:
ULONG_MAX(オーバーフロー)
変換文字列の書式
[空白][符号][0][xまたはX][数値]。

base(基数)が0のときは「変換文字列」から次のように決定します。
  • 01~07のとき8進数。
  • 0xまたは0Xのとき16進数。
  • 1~9のとき10進数。

エラーが発生したとき「errno」(グローバル変数)にERANGEが設定されます。


※「strol()」との違いは戻り値だけです。

■文字列 → double型
関数名 書式 ヘッダー 引数/戻り値 備考
atof() double atof(const char *nptr); <stdlib.h>
【*nptr】
先頭に数値が含まれる文字列。
【戻り値】
変換された数値。失敗時は0。
数値は10進数。
strtod() double strtod(
 const char *nptr,
 char **endptr);
<stdlib.h>
【*nptr】
先頭に数値が含まれる文字列。
【**endptr】
文字列中で変換が終了した位置の文字列を示すポインタ。
【戻り値】
成功時:
変換された数値。
失敗時:
HUGE_VAL(オーバーフロー)
0(アンダーフロー)
変換文字列の書式
[空白][符号][0][xまたはX][数値]。
エラーが発生したとき「errno」(グローバル変数)にERANGEが設定されます。

・サンプルソース(sample0204.c)

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

int main(void) {
    char *str = "012ABC345";
    char *endptr;
    long lval;
    unsigned long ulval;

    printf("atoi() ==============================================\n");
    printf( "%d\n", atoi(str));
    printf("atol() ==============================================\n");
    printf( "%ld\n", atol(str));
    printf("atof() ==============================================\n");
    printf( "%f\n", atof(str));
    printf("strtol() ============================================\n");
    lval = strtol(str, &endptr, 0);
    if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
        || (errno != 0 && lval == 0)) {
        perror("strtol");
    }
    if (endptr == str) {
        fprintf(stderr, "strtol:数値が見つかりません。\n");
    }
    if (*endptr != '\0') {
        printf("未変換文字があります。: %s\n", endptr);
    }
    printf("%li\n", lval);
    printf("strtoul() ===========================================\n");
    ulval = strtoul(str, NULL, 10);  /* 「endptr」を参照しない場合はNULL */
    if ((errno == ERANGE && ulval == ULONG_MAX)
        || (errno != 0 && ulval == 0)) {
        perror("strtoul");
    }
    printf("%lu\n", ulval);
    printf("strtod() ============================================\n");
    printf( "%f\n", strtod(str, NULL));

    return 0;
}

・実行結果

C:\dev\c>sample0204 [Enter]
atoi() ==============================================
12
atol() ==============================================
12
atof() ==============================================
12.000000
strtol() ============================================
未変換文字があります。: ABC345
10
strtoul() ===========================================
12
strtod() ============================================
12.000000
        

▲PageTop