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
変数を使用するには、次のように宣言します。
データ型 変数名;
また変数を”,”(カンマ)で区切って複数の変数を宣言する事も出来ます。
データ型 変数名1, 変数名2, ・・・;
例えばint型の変数aに10代入する場合はこのようになります。
int a; a = 10;
また次のように宣言と同時に値の代入(初期化)することも可能です。
int a = 10;
変数名には次の約束があります。
・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」
異なった型の変数で演算や代入を行うとき、C言語では自動的に型変換(暗黙の型変換)が行われます。また強制的に型を指定する事も可能で、これを明示的型変換(キャスト)といいます。
暗黙の型変換が行われるのは主に次のような場合です。
この場合、一番大きい型に統一されます。このような型変換を「型の昇格」と呼びます。
型の順位は次のようになります。
char < short < int < long < float < double
但し、int型よりも小さい型はすべてint型に統一されます。これを「汎整数拡張」といいます。
この場合は、左辺の型に変換されます。もし左辺の型が右辺より小さいければ情報落ちが発生しますので注意が必要です。
・サンプルソース(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言語には型変換を行う次の関数が用意されています。
関数名 | 書式 | ヘッダー | 引数/戻り値 | 備考 |
atoi() | int atoi(const char *nptr); | <stdlib.h> |
|
数値は10進数。 |
関数名 | 書式 | ヘッダー | 引数/戻り値 | 備考 |
atol() | long atol(const char *nptr); | <stdlib.h> |
|
数値は10進数。 |
strtol() |
long strtol( const char *nptr, char **endptr, int base); |
<stdlib.h> |
|
|
関数名 | 書式 | ヘッダー | 引数/戻り値 | 備考 |
strtoul() |
unsigned long strtoul( const char *nptr, char **endptr, int base); |
<stdlib.h> |
|
エラーが発生したとき「errno」(グローバル変数)にERANGEが設定されます。 ※「strol()」との違いは戻り値だけです。 |
関数名 | 書式 | ヘッダー | 引数/戻り値 | 備考 |
atof() | double atof(const char *nptr); | <stdlib.h> |
|
数値は10進数。 |
strtod() |
double strtod( const char *nptr, char **endptr); |
<stdlib.h> |
|
|
・サンプルソース(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