数値変数と型、scanf

数値変数と型、scanf

何か値を入れて保存しておくための箱である変数と、その変数の種類を表す型について。タイプキャスト(型変換)について。数値の入力を scanf 関数で読み取る方法について。
サイト全体の目次

稿


稿

変数と型

このセクションのリスト

/*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*/ }

list-1.3.1-05

変数とは「何か」を入れておくための「箱」です。結論的なことを言ってしまえば、例えば

int x = 10;

のようにすると、それ以降、「x」と書けばそれは「10」と書いたのと同じことになります。

それではもう少し詳しい説明をします。まず、「箱」つまり「変数」を作ります。方法は

[型] [変数名];

で、
int x;

なら「int」が型、「x」が変数名になります。変数をこのようにして作ることを変数を宣言すると言います。ここで、変数名はその箱につけられた名前であることは分かると思いますが、では「型」とはなんでしょうか。

「型」はその変数にどのような種類(整数、小数、文字等)のデータを入れるかを表したものです。そしてこの「int」はシステムに依存した符号付整数を意味します。どのような型があるのか、変換文字と照らし合わせて.にまとめてみたのでご覧ください。ここで「char」は多くの場合、文字として扱うことが多いのですが、8bit の整数として使うことも出来ます。特に「unsigned char」として1バイトを扱う場合によく使われます。また、8進や16進に対応した変数が無いように思えますが、内部的には10進も8進も16進も同じですので特に用意されていません。

変数名についても少し説明しておきます。変数の名前は31文字以下で次の4つの条件に従わなければなりません。1. 先頭は英字である。2. 空白はつかってはいけない。3. 予約語と同じ名前であってはならない。4. 他に使われている変数名、関数名を使ってはならない。また、大文字、小文字は区別されるので注意してください。空白を入れたい時は代わりに「_(アンダースコア)」を使いましょう。

変数を複数宣言する場合、型が同じであれば次のようにして一行にまとめて書くことができます。

int x, y, z;

これで int 型の変数「x」「y」「z」ができました。

なお、変数は C99 であれば好きな場所で宣言できますが、C99 以前のものでは関数の中で一番最初に行わなければいけません (*1) 。

正確には「ブロック」と呼ばれるものの最初に宣言するのですが、詳しくは別の章で解説します。

list-1.3.1-09

さて、宣言されたばかりの変数は空っぽです。正確には不定といってどのような値が入っているか分からない状態です。そこで変数に「何か」を入れてやります。この操作を代入と言います。書式は

[変数名] = [値];
例:x = 10;

で、これで変数に値が入ります。例は「変数 x は 10 である」と言ってわけです。このようにC言語では「=」は代入を意味し、決して「等しい」ことを表すのではないことに注意してください。

また、変数は一度代入していても後から別の値を代入することができます。特に一番最初の代入を初期化などと言う場合があります。

さらに変数は宣言と同時に初期化することができます。書式は

[型] [変数名] = [値];
例:int x = 10;

で、例では変数 x を宣言すると同時に x には「10」が代入されます。

値が代入された変数はそれ以降、その値の代わりとして自由に使うことが出来ます。

list-1.3.1-11

では変数を使った例を示します。

z = x + y;

はどうでしょうか。この時点でそれぞれ x には 10 が、y には 20 が入っているので、これは
z = 10 + 20;

と書いているのと同じことです。決して変数の中に変数を入れているわけではありませんので注意してください。ですが、逆に
z = x + y;
x = 10;
y = 20;

とするのは誤りです。文法上は問題ないのですが、最初の z へ代入する時点で x も y も不定なので、z の値も不定になります。よく初期化されていない変数には 0 が入っていると勘違いしてしまいやすいので気をつけてください。

list-1.3.1-12

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*/ 

list-1.3.2-08

代入は基本的に同じ型同士で行わなければいけません。違う型を代入する場合はタイプキャスト(型変換)という方法でそれを明示しなければなりません。タイプキャストは

[代入先変数] = (代入先変数の型)[変数]
例:y = (float)x;

という形で行います。例は、変数 y が float 型であるとき、float 型で無い変数 x の値を y に代入しています。このとき、x が int 型などの整数なら大抵の場合問題ないのですが、では逆に int 型の変数へ float 型の変数の値を代入する場合はどうでしょうか?この場合、小数点以下がどのように処理されるかはシステム依存となります。また、short 型の変数にその範囲を超えた値を保持する long 型変数の値を代入するときも、その動作はどうなるか分かりません。ですのでタイプキャストは十分に注意して行ってください。

scanf

このセクションのソース

最後に、キーボードなどからの入力を取得し、数値変数へ値を格納する方法を解説します。

/*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*/ }

list-1.3.3-09

この scanf 関数でキーボードからの数値入力を行ないます。書式は

scanf("[変換文字]", &[変数])

で、ほとんど printf のような形式です。変換文字と変数の型の対応も printf と同様です。これで変数「x」にキーボードから入力された値が格納されます。

ただ、第一引数は文字列ですが変換文字以外の文字を書いても、表示されません。第一引数に書いた変換文字に従って値が読み込まれます。値を入れる変数に適した変換文字を使ってください。また printf と同じ形式で読み込む桁数を指定することができます。注意して欲しいのは変数の前に「&」を付けることで、これは変数の値を渡すのではなく変数の場所を指定しているためなのですが、詳しいことは別の章で解説します。また、以下のように「%d」を2つ並べ、変数も2つ書く(もちろん「,」で区切る)ことで、一度に入力することもできます。

scanf("%d%d", &x, &y);   /*スペースは入れないほうが誤作動を防げる*/

この場合、入力時はスペースもしくは Enter で分けて入力します。このとき、変数へは並んでいるとおりに代入されます。もちろん、「%d」と「%f」でもかまいませんし、3つ以上でもかまいません。

コラム

bit、byteと2進数

「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なんでしょうね。

練習問題

(untitled)

注:本章の問題は、処理系によって左右される場合があります。即ち、C言語の文法上正確ではないがエラーにはならないような場合、処理系依存で適当な値にされてしまうことがあります。なので、解答例とは必ずしも同じ結果が得られないかもしれません。

問題-1.3.1

double 型変数を宣言して適当な値を代入し、この変数の値を printf 関数で整数用変換文字(%d)を使って表示させるとどうなるか確認してください。逆に int 型変数を浮動小数点数用変換文字(%f 又は %lf)で表示させるとどうなるか確認してください。

問題-1.3.2

問題-1.3.1 で、printf 関数に引数として与えた各変数をキャストするとどうなるか確認してください。

問題-1.3.3

問題-1.3.1、問題-1.3.2 について printf 関数ではなく、変数へ代入するとどうなるか確認してください。例:double 型変数 z を宣言して適当な値を代入、これを int 型変数 n に代入する。次に、z をキャストして n に代入してみる。

練習問題回答例

問題-1.3.1

まったく違った値が表示されます。以下、double 変数のときの例

#include <stdio.h>

main()
{
	double z = 123.45;
	/* z = 123 としても、それは 123.0 という小数 */

	printf("%d\n", z);

	return 0;
}

問題-1.3.2

表示はされますが、double を int にキャストした場合は適当な値に変換されます。(変換方法は処理系依存で、切り捨てや四捨五入。)

#include <stdio.h>

main()
{
	double z = 123.45;

	printf("%d\n", (int)z);

	return 0;
}

問題-1.3.3

以下、普通に 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;
}


読み込み中・・・
10秒待っても表示が変わらない場合、次の理由が考えられます。
・Javascript が無効になっています。
・検索エンジンのキャッシュを見ています。
サイトホームへ / 上位ページへ / ページトップへ / PAROFトレンドショッピングへ
Copyright (C) 2010 totobon all right reserved.