C言語での演算処理
演算
第一日目では、printf()関数を用いて、様々な演算をしてみました。その中で、C言語を用いれば、簡単な計算が出来ることがわかりました。そこで、ここでは、C言語を用いた計算について学んでいくことにしましょう。
プログラミングの世界では、こういった計算のことを、専門用語で演算と呼びます。これは、以下、簡単な演算のプログラムをみてみることにしましょう。
サンプロプログラム
list2-1:簡単な演算処理(main.c)#include <stdio.h> /* 演算子を用いた計算のプログラム */ void main() { // 各種演算 printf("%d + %d = %d¥n",5,2,5+2); /* 足し算 */ printf("%d - %d = %d¥n",5,2,5-2); /* 引き算 */ printf("%d * %d = %d¥n",5,2,5*2); /* 掛け算 */ printf("%d / %d = %d 余り %d ¥n",5,2,5/2, 5 % 2); /* 割り算 */ }
5 - 2 = 3
5 * 2 = 10
5 / 2 = 2 余り 1
実行結果からもわかるとおり、このプログラムを実行すると、様々な計算結果が出てきます。
演算子
このように、C言語で様々な演算を行う記号のことを演算子(えんざんし)と呼びます。足し算の+や、引き算の-はわかるものの、その他の記号は何でしょう?C言語で使用する演算子は以下の表2-1のようなものがあります。
演算子 | 読み方 | 意味 | 使用例 |
---|---|---|---|
+ | プラス | 足し算を行う演算子 | 5 + 5 |
- | マイナス | 引き算を行う演算子 | 7 - 3 |
* | アスタリスク | 掛け算を行う演算子 | 7 * 3 |
/ | スラッシュ | 割り算を行う演算子 | 7 / 3 |
% | パーセント | 剰余(じょうよ)演算子。割り算の余り | 7 % 3 |
評価和わかるとおり、*が掛算、/が割り算を表す記号であることがわかると思います。また、%の記号は、かなりC言語のプログラミングでは使用頻度が高いので、覚えておきましょう。
コメント
ところで、このプログラムの中に、出てくる//や、/* */という記号が出てきます。しかも、その中には、文章が書いていますが、プログラムの実行結果には何も関係ないように見えます。この記号のことを、コメントと言います。
コメントは、プログラムの注釈を付けるためのもので、プログラマーが、プログラムの各所に書いて、処理の意味などを記述する時に用いられます。実行結果には何ら影響を与えませんが、これを付けるとプログラムが非常にわかりやすくなります。
そのため、プログラマーは、出来るだけコメントをつけるようにすることが勧められています。なお、コメントには、以下(表2-2)のような種類があります。
記述方法 | 名前 | 特徴 | 使用例 |
---|---|---|---|
/* */ | ブロックコメント | /*と、*/の間に囲まれた部分がコメントになる。 複数行にわたってコメントをつけることが出来る。 |
/* このように複数行 コメント可能です。 */ |
// | 行コメント | 一行にコメントをつけることが出来る。 | // コメント |
変数
C言語と変数
C言語を用いれば、様々な演算ができることはすでにわかりました。しかし、これでは、決められた値の計算しかできません。実際は、色々な数値を用いて計算することが想定されるため、これでは不便です。 このように、値が定まった数のことを、定数と言いますが、それに対し、C言語には、値を常に変えることができる数が存在するのです。これを、変数と言います。
サンプルプログラム
まずは、以下のサンプルを実行してみてください。
list2-2:変数を用いた演算処理(main.c)#include <stdio.h> /* 変数を用いた計算 */ void main() { /* 使用する変数の定義 */ int a; // 変数の宣言 int b = 3; // 初期化と代入を同時に行う。 int add,sub; // 複数の変数を同時に宣言 double avg; // int以外の変数を宣言 a = 6; // 代入(最初に値を入れるので、”初期化”と言う。 add = a + b; // a,bの和を求める。 sub = a - b; // a,bの差を求める。 avg = (a + b) / 2.0; // a,bの平均値を求める。 printf("%d + %d = %d¥n",a,b,add); printf("%d - %d = %d¥n",a,b,sub); printf("%dと%dの平均値:%f¥n",a,b,avg); }
6 - 3 = 3
6と3の平均値 4.500000
プログラムの中にa、b、add、sub、avgといった文字列が出ていますが、これが変数です。int aとある部分を、変数の宣言と言います。そのあと、a=6のようにすると、値が入ります。これを代入と言います。(図2-1)特に、変数を宣言したときに、最初に行う代入のことを、初期化と言います。
代入
数値が代入された変数は、その数値として扱う事が出来ます。例えば、a=6とすれば、aは別の値が代入されるまで、"6"として扱う事が出来ます。変数は原則的に何度も値を変えることが可能です。つまり、変数は値を変えることが出来るのです。
変数の初期化と代入a = 6; ← 代入。(変数に値を入れる)
図2-1.変数の宣言と代入のイメージ
演算の優先順位
プログラム中に、()(括弧)がありますが、これは、計算の優先順位を変更するものです。通常、
括弧が無い場合の計算とすると、最初に掛け算の演算である「2*3」が実行され、その結果の6に1が加算されます。したがって、結果は7になります。しかし、
括弧を用いた計算とすると、()内の計算を先に行い、その結果である、3と次の3が掛けられることになります。このように、C言語にも、数学と同じような演算子の優先順位があります。 C言語には様々な演算があるため、ここでは全てを説明するのは省略しますが、加減乗除といった基本的な数値計算に関しては、数学と同じルールに従うと思ってほぼ間違いありません。(図2-2)
図2-2.()を使用した場合と、使用しない場合の演算の処理
データ型
では、初期化の際に変数の先頭についている、intや、doubleといった文字列は何でしょうか?このような文字列のことを、データ型と言い、その変数がどのような値を扱うのかを示しています。 例えば、intは、整数型のデータ型を表し、"int a"とすると、"aは整数の値が入る変数である。"ことを意味します。なお、データ型には以下のようなものがあります。(表2-3)
データ型 | 説明 |
---|---|
char | 1バイトの符号付整数。ASCIIコードといった文字コードに使用。 |
unsigned char | 1バイトの符号なし整数。 |
short | 2バイトの符号付整数。 |
unsigned short | 2バイトの符号なし整数。 |
long | 4バイトの符号付整数。 |
unsigned long | 4バイトの符号なし整数。 |
int | 2または4バイトの符号付整数。(コンパイラに依存) |
unsigned | 2バイトまた4バイトの符号なし整数。(コンパイラに依存) |
float | 4バイトの単精度浮動小数点実数。 |
double | 8バイトの倍精度浮動小数点実数。 |
表に出ているように、intは、2バイトか4バイトのどちらかであり、2バイトとの場合は、shortと、4バイトの場合は、longと一致します。 近頃のコンパイラや実行環境は、4バイト、つまりlongとおなじにしているものがほとんどのようです。
初期化
再び変数の話に戻りましょう。変数は、宣言時に値を代入(初期化)することが出来ます。記述方法は以下のとおりです。
変数の宣言と初期化を同時に行うint a = 6; | ← 変数の宣言と同時に値を代入(初期化) |
また、以下のように、,(コンマ)で区切ることにより同時に複数の変数を宣言したり、初期化することも可能です。
複数の変数を同時に宣言int a,b; | ← 変数a,bを宣言 |
int a=1,b=2; | ← 変数a,bを初期化 |
int a,b=1; | ← 変数a,bを宣言、bのみを初期化 |
なお、プログラミングにおいて、変数は必ず初期化して使うというルールがあります。初期化していない変数を使用すると、プログラムが異常終了することがありますので、気をつけてください。
変数の初期化の位置
また、変数の宣言をする場所ですが、必ず{}の先頭の部分で行わなくてはなりません。以下のように、何らかの処理が行われた後で変数を定義すると、エラーになりますので、注意が必要です。
変数の宣言の位置に関する注意{
// 先頭の部分で変数の宣言を行う。
int a,b=1;
double d=0.1,e;
printf("hello¥n");
int c; ←×何らかの処理を行った後に変数の宣言を入れることはできない。
・・・
}
この規則は、C言語の上位互換言語であるC++では撤廃されましたが、C言語でプログラムを作るうえでは必要なので、注意してください。
変数の命名規則
C言語の変数の命名規則
変数の名前は、基本的にプログラマーが自由につけることが許されています。通常、アルファベット一文字か、その組み合わせといったものが使われる場合がほとんどです。しかし、何でも良いというわけではなく、以下のようなルールがあります。
- 使用できる文字は半角の英文字(A~Z,a~z)、数字(0~9)、アンダーバー(_)。(例:abc、i、_hello、num1など)
- 変数名の最初の文字を数字にすることは出来ない。必ず英文字およびアンダーバーからはじめること。(例:a123 → ○ 123a → ×)
- 英文字の大文字と小文字は別の文字として扱われる。(例:ABCとabcは違う変数とみなされる。)
- 規定されているC言語の予約語を使ってはいけない。
予約語
なお、予約語とは言語の仕様で使い方が決められている単語のことで、C言語の予約語は以下のとおりです。(表2-4)
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 |
代入演算子
代入と演算
すでに述べたとおり、変数に値を入れることを代入と言いました。代入とは例えば以下のように記述します。
代入処理a = 1; | ← 変数aに1を代入 |
a = b; | ← 変数aに変数bの値を代入 |
d = 4.0; | ← 変数dに4.0を代入 |
ここで気をつけたいのが、代入で使用する=(イコール)記号の意味です。数学で、=記号は、左辺と右辺の値が等しい、という場合に用いられる記号です。しかし、C言語で代入に用いる=は、少し意味が違います。
代入におけるイコールは、右辺の値を左辺の変数に代入するという意味になるのです。そのため、例えば
自身を用いた計算結果を代入するa = a + 1; | ← ① aに、a+1の値を代入する。 |
b = b * 5; | ← ② bに、b*5の値を代入する。 |
といった記述方法も可能になります。例えば、①ですが、仮に最初の段階でaに4が入っていたとすると、そこに1を足した5がaに代入されます。についても同様で、bに2が入っていたら、2に5をかけた値、つまり10がbに入ります。
list2-3:変数を用いた演算処理(main.c)#include <stdio.h> /* 代入演算子をを用いた計算 */ void main() { /* 使用する変数の定義 */ int a1=2,b1=2,c1=2,d1=2; // 変数の宣言(1) int a2=2,b2=2,c2=2,d2=2; // 変数の宣言(2) // 普通の演算による計算と代入 a1 = a1 + 1; b1 = b1 - 1; c1 = c1 * 2; d1 = d1 / 2; // 代入演算による計算 a2 += 1; b2 -= 1; c2 *= 2; d2 /= 2; printf("a1=%d b1=%d c1=%d d1=%d¥n",a1,b1,c1,d1); printf("a2=%d b2=%d c2=%d d2=%d¥n",a2,b2,c2,d2); }
a2=3 b2=1 c2=4 d2=1
代入演算子
実行結果を見れば判る通り、a1とa2~d1とd2の組み合わせはそれぞれ、記述の仕方が違うだけで、結果が同じであることが判ります。このように、代入演算を用いれば、短い記述で同様の結果を得ることが出来ることがわかります。
なお、C言語における主な代入演算は、以下のとおりです(表2-5)。演算子 | 使用例 | 意味 |
---|---|---|
+= | a+=1; | a=a+1; |
-= | a-=1; | a=a-1; |
*= | a*=2; | a=a*2; |
/= | a/=2; | a=a/2; |
%= | a%=2; | a=a%2; |
キャストとデータの型変換
サンプルプログラム
次に、型の異なる変数に値を代入するケースを見てみましょう。例えば、整数型の変数の値を実数型の変数に代入するような処理です。以下のサンプルを見てみましょう。
list2-4:キャストとデータの型変換(main.c)#include <stdio.h> void main(){ int i1,i2,j1,j2; double d1,d2,e1,e2; // j1,j2に値を代入 j1 = 3; j2 = 3; // d1,d2に値を代入。 d1 = 1.23; d2 = 1.23; // i1,i2にd1,d2の値を代入 i1 = d1; // 普通に代入 i2 = (int)d2; // キャストして代入 // e1,e2にj1,j2の値を代入 e1 = j1; // 普通に代入 e2 = (double)j2; // キャストして代入 printf("d1 = %f d2 = %f¥n",d1,d2); printf("i1 = %d i2 = %d¥n",i1,i2); printf("j1 = %d j2 = %d¥n",j1,j2); printf("e1 = %f e2 = %f¥n",e1,e2); }
i1 = 1 i2 = 1
j1 = 3 j2 = 3
e1=3.000000 e2=3.000000
キャスト
このプログラムでは、double型からint型の変換(d1,d2から、i1,i2)と、int型から変換からdouble型への変換(j1,j2から、e1,e2)を行っています。 実行結果から見てわかるとおり、前者の場合、小数点以下の数値が切り捨てられ、後者の場合は、該当する整数のあとに「.000000」がつく実数に変換されていることがわかります。
14行目と、17行目では、変換する値への型変換(キャスト)が行われています。
変数の型変換(キャスト)e2 = (double)j2;
i2はint型の変換なので、double型の変数を代入する際、先頭に(int)とつけ、e2は(double)なので、先頭に(int)とつけることにより、型の変換を行います。 整数から実数への変換の場合は特に必要ありませんが、実数から整数の変換のように、桁落ちなど、データの一部が損なわれる可能性がある場合必要です。
警告
キャストがなくても、結果は変わりませんが、13行目で、キャストなしの処理を入れると、以下のような警告が発せられます。
実数→整数の変換でコンパイル時に出る警告これ自体はエラーではありませんが、通常ソフトウェアを開発する場合、警告を完全に取り去る必要があるので、同様の処理を行う際には、キャストを行うようにしましょう。
以上で、演算と変数に関するお話は終了です。次からは、この変数を用いていろいろな処理を行っていくことにしましょう。
練習問題 : 問題2.