/*01*/ #include <stdio.h>
/*02*/
/*03*/ main()
/*04*/ {
/*05*/ int x;
/*06*/ int y;
/*07*/ int z;
/*08*/
/*09*/ x = 10;
/*10*/ y = 20;
/*11*/ z = x + y;
/*12*/ printf("%d + %d = %d\n", x, y ,z);
/*13*/
/*14*/ return 0;
/*15*/ }
int x = 10;
それではもう少し詳しい説明をします。まず、「箱」つまり「変数」を作ります。方法は
[型] [変数名];
int x;
「型」はその変数にどのような種類(整数、小数、文字等)のデータを入れるかを表したものです。そしてこの「int」はシステムに依存した符号付整数を意味します。どのような型があるのか、変換文字と照らし合わせて.にまとめてみたのでご覧ください。ここで「char」は多くの場合、文字として扱うことが多いのですが、8bit の整数として使うことも出来ます。特に「unsigned char」として1バイトを扱う場合によく使われます。また、8進や16進に対応した変数が無いように思えますが、内部的には10進も8進も16進も同じですので特に用意されていません。
変数名についても少し説明しておきます。変数の名前は31文字以下で次の4つの条件に従わなければなりません。1. 先頭は英字である。2. 空白はつかってはいけない。3. 予約語と同じ名前であってはならない。4. 他に使われている変数名、関数名を使ってはならない。また、大文字、小文字は区別されるので注意してください。空白を入れたい時は代わりに「_(アンダースコア)」を使いましょう。
変数を複数宣言する場合、型が同じであれば次のようにして一行にまとめて書くことができます。
int x, y, z;
なお、変数は C99 であれば好きな場所で宣言できますが、C99 以前のものでは関数の中で一番最初に行わなければいけません (*1) 。
さて、宣言されたばかりの変数は空っぽです。正確には
[変数名] = [値]; 例:x = 10;
また、変数は一度代入していても後から別の値を代入することができます。特に一番最初の代入を
さらに変数は宣言と同時に初期化することができます。書式は
[型] [変数名] = [値]; 例:int x = 10;
値が代入された変数はそれ以降、その値の代わりとして自由に使うことが出来ます。
では変数を使った例を示します。
z = x + y;
z = 10 + 20;
z = x + y; x = 10; y = 20;
printf で変数を表示するには、その型に合った変換文字を使用します。どの型がどの変換文字と対応しているかは.に示したとおりです。
| 符号付整数 | ||
| char | (%d) | 符号付8bit整数 |
| short | (%d) | 符号なし8bit整数 |
| int | %d | システムに依存した範囲の符号付整数 |
| long | %ld | 符号付32bit整数 |
| long long | %lld | 符号付64bit整数(C99) |
| 符号なし整数 | ||
| unsigned char | (%u) | 符号なし8bit整数 |
| unsigned short | (%u) | 符号なし16bit整数 |
| unsigned int | %u | システムに依存した範囲の符号なし整数 |
| unsigned long | %lu | 符号なし32bit整数 |
| unsigned long long | %llu | 符号なし64bit整数(C99) |
| 符号なし整数の8進数、16進数表示 | ||
| %o | システムに依存した範囲の8進数 | |
| %lo | 符号なし32bit整数を8進数で表示 | |
| %x | システムに依存した範囲の16進数 | |
| %lx | 符号なし32bit整数を16進数で表示 | |
| 浮動小数点数 | ||
| float | %f | 32bit(単精度)浮動小数点数 |
| double | %lf | 64bit(倍精度)浮動小数点数 |
| %e | 32bit(単精度)浮動小数点数を指数形式で表示 | |
| %le | 64bit(倍精度)浮動小数点数を指数形式で表示 | |
| 文字 | ||
| char | %c | 一文字 |
| char 配列 | %s | 文字列 |
▲システムに依存した範囲とは、例えば16bit環境なら16bit整数、32bit環境なら32bit整数となる。
▲符号付Nbit整数とは「-2の(N/2)乗~2の(N/2)乗-1」の範囲。例えば32bitなら「-2の16乗~2の16乗-1」で「-2,147,483,648 ~ 2,147,483,647」となる。
▲符号なしNbit整数とは「0~2のN乗-1」の範囲。例えば32bitなら「0~2の32乗-1」で「4,294,967,295」となる。
▲浮動小数点数の指数形式表示は「1.234E+3」や「1.234E-3」のような形になり、前者は「1.234×10の3乗」を、後者は「1.234×10の-3乗」を意味する。
▲32bit浮動小数点数の範囲は「3.4E±38」、64bit浮動小数点数の範囲は「1.7E±308」となる。
▲「short」「long」「long long」はそれぞれ「short int」「long int」「long long int」の省略形。
/*01*/ #include <stdio.h>
/*02*/
/*03*/ main()
/*04*/ {
/*05*/ int x = 10;
/*06*/ float y;
/*07*/
/*08*/ y = (float)x;
/*09*/ printf("%f\n", y);
/*10*/
/*11*/ return 0;
/*12*/ }
/*13*/
代入は基本的に同じ型同士で行わなければいけません。違う型を代入する場合は
[代入先変数] = (代入先変数の型)[変数] 例:y = (float)x;
最後に、キーボードなどからの入力を取得し、数値変数へ値を格納する方法を解説します。
/*01*/ #include <stdio.h>
/*02*/
/*03*/ main()
/*04*/ {
/*05*/ int x, y, z;
/*06*/
/*07*/ printf(" x と y の値を入力してください。\n");
/*08*/ printf(" x -> ");
/*09*/ scanf("%d", &x);
/*10*/ printf(" y -> ");
/*11*/ scanf("%d", &y);
/*12*/ z = x + y;
/*13*/ printf(" %d + %d = %d\n", x, y, z);
/*14*/
/*15*/ return 0;
/*16*/ }
この scanf 関数でキーボードからの数値入力を行ないます。書式は
scanf("[変換文字]", &[変数])
ただ、第一引数は文字列ですが変換文字以外の文字を書いても、表示されません。第一引数に書いた変換文字に従って値が読み込まれます。値を入れる変数に適した変換文字を使ってください。また printf と同じ形式で読み込む桁数を指定することができます。注意して欲しいのは変数の前に「&」を付けることで、これは変数の値を渡すのではなく変数の場所を指定しているためなのですが、詳しいことは別の章で解説します。また、以下のように「%d」を2つ並べ、変数も2つ書く(もちろん「,」で区切る)ことで、一度に入力することもできます。
scanf("%d%d", &x, &y); /*スペースは入れないほうが誤作動を防げる*/
「bit」は「ビット」と読みます。「byte」は「バイト」と読みます。さて、皆さんコンピュータの基本は2進数であることは知っていると思います。「コンピュータの世界は 0 か 1 、あるか無いかのデジタルの世界だ。」と。この最小単位「0」 or 「1」で構成されるのが「1ビット」です。そして「8ビット」になると「1バイト」になります。この後はもう分かりますよね。1024バイトで「1キロ・バイト」、1024キロ・バイトで「1メガ・バイト」、その上に「ギガ」「テラ」と続きます。そこで皆さんの持っているファイルを何でもいいので見てください。何バイトになっていますか?もしそれが「10メガ・バイト」だったら、そのファイルを「0」「1」に分解すれば、それが「10 × 1024 × 1024 × 8 = 83,886,080個」並んでいることになるのです。
では、「100」という数字をあらわすには何ビット必要でしょう。1ビットで2つあらわせますね。2ビットなら 2 × 2 = 4つ、3ビットなら 2 × 2 × 2 = 8つ、つまり、「nビット」ということは「2のn乗個」のものがあらわせるわけです。そうすると、「100」は 64 < 100 < 128 ですから、128 = 2の7乗で7ビットあればいいわけです。
次に「Windows 95 以降は 32ビット 処理だ」ということを聞いたことがあるでしょうか。それ以前の Windows 3.1 などは 16ビット 処理と呼ばれるものでした。これは、 Win 95 以降の場合、「32ビットづつ処理が出来る。」ということです。そのため、変数の型に「int」としてやると OS の処理しやすい 32ビット(4バイト) = 2の32乗 = 4,294,967,296個 の、また、16ビット OS なら、「int」は 65536個の数字があらわせるわけです。ただし2進数の一番左の部分は +- の符号になりますから、実際にあらわせる数値は「0」も含めて32ビットで「-2,147,483,648 ~ 2,147,483,647」、16ビットで「-32,768 ~ 32,767」です。これが「符号無し int(unsigned int)」だと、一番左の符号が無くなるので32ビットなら「0 ~ 4,294,967,295」、16ビットなら「0 ~ 65535」となります。
そうそう、中には昔「ファミコン」で遊んだ人もいるでしょう。あれって、どんなにがんばっても機数が255までしかアップしないゲーム、ありませんでしたか?これってきっと、機数を 8ビット(1バイト) = 2の8乗(256) で定義したから「0」も含めて最大が255なんでしょうね。
注:本章の問題は、処理系によって左右される場合があります。即ち、C言語の文法上正確ではないがエラーにはならないような場合、処理系依存で適当な値にされてしまうことがあります。なので、解答例とは必ずしも同じ結果が得られないかもしれません。
double 型変数を宣言して適当な値を代入し、この変数の値を printf 関数で整数用変換文字(%d)を使って表示させるとどうなるか確認してください。逆に int 型変数を浮動小数点数用変換文字(%f 又は %lf)で表示させるとどうなるか確認してください。
問題-1.3.1 で、printf 関数に引数として与えた各変数をキャストするとどうなるか確認してください。
問題-1.3.1、問題-1.3.2 について printf 関数ではなく、変数へ代入するとどうなるか確認してください。例:double 型変数 z を宣言して適当な値を代入、これを int 型変数 n に代入する。次に、z をキャストして n に代入してみる。
まったく違った値が表示されます。以下、double 変数のときの例
#include <stdio.h>
main()
{
double z = 123.45;
/* z = 123 としても、それは 123.0 という小数 */
printf("%d\n", z);
return 0;
}
表示はされますが、double を int にキャストした場合は適当な値に変換されます。(変換方法は処理系依存で、切り捨てや四捨五入。)
#include <stdio.h>
main()
{
double z = 123.45;
printf("%d\n", (int)z);
return 0;
}
以下、普通に int 型変数 n へ double 型変数 z を代入した例です。エラー(error)にはなりませんが、コンパイル時に警告(warning)がでます。また、このときは 問題 3-2 の時と同様適当な値に変換されます。
#include <stdio.h>
main()
{
double z = 123.45;
int n;
n = z;
printf("%d\n", n);
return 0;
}
以下、キャストして int 型変数 n へ double 型変数 z を代入した例です。コンパイル時の警告(warning)はでなくなりますが、やはり適当な値に変換されます。
#include <stdio.h>
main()
{
double z = 123.45;
int n;
n = (int)z;
printf("%d\n", n);
return 0;
}