- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- ソース を表示
- 授業/C言語基礎/変数の高度な使い方 へ行く。
- 1 (2015-12-14 (月) 11:08:07)
- 2 (2015-12-14 (月) 13:12:25)
- 3 (2015-12-14 (月) 17:04:03)
- 4 (2015-12-15 (火) 01:26:33)
- 5 (2015-12-15 (火) 09:07:41)
- 6 (2015-12-15 (火) 19:31:07)
- 7 (2015-12-16 (水) 07:57:25)
- 8 (2015-12-17 (木) 07:04:21)
- 9 (2015-12-17 (木) 13:06:21)
- 10 (2015-12-17 (木) 18:50:17)
- 11 (2015-12-18 (金) 04:21:23)
- 12 (2015-12-18 (金) 09:40:01)
- 13 (2015-12-21 (月) 09:12:03)
- 14 (2015-12-21 (月) 09:12:03)
- 15 (2016-12-16 (金) 10:03:25)
- 16 (2016-12-16 (金) 16:07:36)
- 17 (2016-12-17 (土) 12:47:14)
これまで、int型、double型、そしてchar型という3つのデータ型を使ってきました。
ここでは、
変数名 †
変数の名前は、下線 _、英大文字 A-Z、英小文字 a-z、数字 0-9 で構成され、先頭は数字以外の文字でなければなりません。大文字と小文字は区別されます。
int, double, char, void, return, if, else, while, for, switch, case, default など、あらかじめ決められているキーワード(予約語)と同じ名前を使うことはできません。
習慣的に、C言語では変数名を小文字にします。
基本データ型 †
char型 †
char型は、文字を表します。 整数として扱うことができます。
符号付き整数型 †
これまで使ってきたint型は、符号付きの整数を表します。 符号付きであることは省略できるので、これまでは省略していました。 省略せずに書くと、signed int型です。
int型の記憶容量(サイズ)を基本として、int型より小さいサイズにしたり、大きいサイズにすることができます。
符号付き整数型をサイズの小さい順に並べると、次のようになります。
- signed char
- short (signed short)
- int (signed int)
- long (long int, signed long int)
- long long (long long int, signed long long int)
ただし、実際のサイズは実行環境に依存します。 long型とlong long型のサイズが同じという環境もあります。
符号なし整数型 †
符号なし整数型は、符号付きであることを表すsignedの代わりに、unsignedと書いて表します。
また、C99から、0または1で論理値を表す_Bool型が追加されました。
符号なし整数型をサイズの小さい順に並べると、次のようになります。
- _Bool
- unsigned char
- unsigned short int (unsigned short)
- unsigned int
- unsigned long (unsigned long int)
- unsigned long long (unsigned long long int)
浮動小数点型 †
double型は、倍精度の浮動小数点数を表します。 浮動小数点数については、計算機アーキテクチャーや数値解析Iの授業できちんと勉強してください。
浮動小数点数型には、double型の半分のサイズのfloat型と、double型よりも大きなサイズのlong double型があります。
(実数を表す)浮動小数点数型をサイズの小さい順に並べると、次のようになります。
- float
- double
- long double
また、C99から、複素数を表す型(型名の後ろに_Complexが付く)が追加されました。
複素数を表す浮動小数点数型をサイズの小さい順に並べると、次のようになります。
- float _Complex
- double _Complex
- long double _Complex
符号付き整数型と符号なし整数型の違い †
符号付き整数型では、先頭ビットが符号を表します。 符号なし整数型には、符号を表すビットは存在しません。
このため、符号なし整数型は、符号付き整数型の約2倍の範囲の数を表すことができます。
次のプログラムは、8ビットの大きさの符号付きchar型と符号なしchar型に、8ビット符号なし整数の最大値である255を代入して表示します(プログラム1)。
signed char sc = 255; unsigned char uc = 255; printf(">> %d\n", sc); printf(">> %d\n", uc);
これを実行すると、次のようになります。
luna% a.out >> -1 >> 255
255は、2進数で表すと 11111111 ですが、符号付き整数では負の数を2の補数として表現するので、これを2の補数として解釈し、-1 と出力されています。 2の補数については、計算機アーキテクチャーの授業できちんと勉強してください。
また、符号付き整数と符号なし整数では、あとで勉強するシフト演算の振る舞いが異なります。
演習1 †
プログラム1を作成し、実行結果を確認せよ。
定数 †
変数がプログラム実行中に変化する可能性がある数であるのに対し、定数はプログラム実行中に変化することがありません。プログラムの中に直接書かれている値も、定数です。
整定数 †
整定数には、10進数、8進数、16進数があります。
10進数は、0 以外の数字で始まり、0 から 9 までの数字だけで表します。 たとえば、10 は、10進数の 10 を表します。 整数をprintf関数を用いて10進数表記で出力するときの変換指定子は %d です。
8進数は、0 で始まり、0 から 7 までの数字だけで表します。 たとえば、010 は、8進数の 10 を表し、10進数にすると 8 です。 符号なし整数をprintf関数を用いて8進数表記で出力するときの変換指定子は %o です。
16進数は、0x で始まり、0 から 9 までの数字と a から f までの英字だけで表します。 たとえば、0x10は、16進数の 10 を表し、10進数にすると 16 です。 符号なし整数をprintf関数を用いて16進数表記で出力するときの変換指定子は %x です。
printf("%d\n", 10); printf("%d\n", 010); printf("%d\n", 0x10); printf("%04x\n", 16);
luna% a.out 10 8 16 0010
浮動小数点定数 †
浮動小数点定数には、10進浮動小数点数、指数表現10進浮動小数点数、指数表現16進浮動小数点数があります。
10進浮動小数点数は、0 以外の数字で始まり、0 から 9 までの数字と小数点だけで表します。 たとえば、1.01 は、10進数の 1.01 を表します。
指数表現10進浮動小数点数は、10進浮動小数点数の後に e と指数部を表す10進数をつけて表します。 たとえば、1.01e2 は、1.01 \times 10^2で 101、1.01e−2 は、1.01 \times 2^{-2}で 0.0101 を表します。
指数表現16進浮動小数点数は、0x で始まり、0 から 9 までの数字と a から f までの英字と小数点、その後に p と指数部を表す10進数をつけて表します。 基数は2なので、指数部は2の何乗倍であるかを表します。 たとえば、0x1.01p12 は、16進数 1.01 の2の12乗倍を表し、2進数 0001.0000 0001 を左に12ビットだけシフトしたものなので2進数 0001 0000 0001 0000、10進数にすると 4,102 です。 printf関数で指数表現16進浮動小数点数の形を出力するときの変換指定子は ''
文字定数 †
文字定数は、シングル・クォーテーションで囲まれた文字です。
英大文字 A-Z、英小文字 a-z、数字 0-9、記号 ! " # % & ( ) * + , - . / : ; < = > ? [ ] ^ { | } ~、または \ で始まるエスケープ・シーケンスのいずれかです。
値を変更できない変数 †
変数を宣言するときに、型名の前に const を付けて宣言すると、その変数には初期化のときにしか値を代入できなくなり、定数となります。
printf("%f\n", 1.01); printf("%f\n", 1.01e2); printf("%f\n", 1.01e-2); printf("%f\n", 0x1.01p12);
型が配列でないときは、初期化子を囲む波括弧 { } は省略できます。
習慣的に、C言語では定数名を大文字にします。
変数の有効範囲(スコープ) †
変数は、宣言する場所によって、その有効範囲が異なります。 変数の有効範囲をスコープといいます。
ブロック有効範囲 †
波括弧 { } で囲まれたブロック内で宣言された変数は、ブロック有効範囲の変数となり、宣言したところからそのブロックの終わりまでだけで有効です。
このような変数を、局所変数、’’ローカル変数''といいます。
次のプログラムは、同じ名前で有効範囲の異なるローカル変数を二つ宣言しています(プログラム2)。
1.010000 101.000000 0.010100 4112.000000
このプログラムに登場する変数のスコープを図で表すと、次のようになります。
同じブロック内ですでに宣言されている変数の名前と同じ名前の変数を宣言することはできませんが、ブロックを作ることで同じ名前の変数を宣言できるようになります。 このとき、変数にアクセスすると、より内側のブロックでの宣言が優先されます。
このプログラムを実行すると、次のようになります。
const 型 定数名 = { 初期化子 };
C99では、for文の丸括弧 ( ) の中でも変数を宣言できるようになりました(プログラム3)。
int main(void) { int i = 0; printf(">> %d\n", i); { int i = 1; printf("## %d\n", i); } printf(">> %d\n", i); return 0; }
ただし、gccでこのプログラムをコンパルするときには、stdオプションにc99を指定する必要があります。
luna% a.out >> 0 ## 1 >> 0
演習2 †
プログラム2とプログラム3を作成し、実行結果を確認せよ。
ファイル有効範囲 †
関数の外で変数を宣言すると、ファイル有効範囲の変数となり、宣言されたところからそのファイルの最後まで全体で有効となります。
このような変数を、大域変数、’’グローバル変数''といいます。
次のプログラムは、同じ名前のグローバル変数とローカル変数を宣言しています(プログラム4)。
for (int i = 0; i < 3; i++) { printf(">> %d\n", i); }
このプログラムに登場する変数のスコープを図で表すと、次のようになります。
有効範囲が赤色で示されているものがファイル有効範囲の変数、青色で示されているものがブロック有効範囲の変数です。
変数にアクセスすると、より内側の宣言が優先されます。
このプログラムを実行すると、次のようになります。
luna% gcc -std=c99 hello.c luna% a.out >> 0 >> 1 >> 2
演習3 †
プログラム4を作成し、実行結果を確認せよ。
変数の有効期限 †
静的記憶域期間 †
自動記憶域期間 †
C言語の規格(おまけ) †
C言語は、1989年にアメリカで最初の標準規格が作られました。 この規格は、ANSI-CやC89と呼ばれています。
これを基にして、1990年にC90と呼ばれる標準規格が世界標準機構 (ISO) で標準規格が作られました。
その後、1999年と2011年に規格が改定され、それぞれ、C99、C11と呼ばれています。 (現在のgccには、C99とC11のほとんどの機能が実装されています。)
C言語の教科書、参考書を読むときには、どの規格に基づいて書かれているのか、確認しておきましょう。
gccでは、stdオプションを指定すると、指定した規格の文法に従ってコンパイルができます。
#include <stdio.h> int i = 0; void prt(void) { printf("## %d\n", i); } void inc(void) { i++; } int main(void) { int i = -1; printf(">> %d\n", i); prt(); inc(); prt(); printf(">> %d\n", i); return 0; }
列挙型(おまけ) †
int型の値で、かつ、取りうる値が決まっているとき、列挙型とすることによって、変数の値を制限することができます。
列挙型は、次のように宣言します。
luna% a.out >> -1 ## 0 ## 1 >> -1
列挙子には、先頭から順に 0, 1, 2 と値が割り当てられますが、代入演算子 = をつけて値を指定することもできます。 また、同じ値を複数の列挙子に割り当てることもできます。
次のプログラムは、enum deptという名前の列挙型を宣言し、変数 d をenum dept型として宣言しています。 こうすることによって、変数 d にはenum dept型の列挙子の並びに宣言された値しか代入できなくなります。
記憶域クラス指定子 型 変数名;
これを実行すると、次のようになります。
void cnt(void) { static int i = 0; i++; printf(">> %d\n", i); } int main(void) { cnt(); cnt(); cnt(); return 0; }
定数の接尾語(おまけ) †
定数の後ろに接尾語をつけて定数の型を明確にすることができます。
整定数 †
接尾語をつけないとint型とみなされます。
接尾語 u は、unsigned int型であることを表します。 接尾語 l は、long型(long int型)であることを表します。 接尾語 ll は、long long型(long long int型)であることを表します。
浮動小数点定数 †
接尾語をつけないとdouble型とみなされます。
接尾語 f は、float型であることを表します。 接尾語 l は、long double型であることを表します。
次のプログラムは、2進数にすると循環小数になるため必ず誤差が生じてしまう10進数の定数 0.1 を表示するプログラムです。
luna% >> 1 >> 2 >> 3
これを実行すると、次のようになります。
void cnt(void) { auto int i = 0; i++; printf(">> %d\n", i); } int main(void) { cnt(); cnt(); cnt(); return 0; }