2. C言語の基本
プログラミングはプログラム言語を使ってコンピュータにあてた文章を組み立てることです。基本的には人間にあてた日本語の手紙や英語の手紙を書くのと変わりません。
この章では、C言語の言語仕様についてまとめておきます。日本語や英語を勉強するときでも同じですが、「日本語には名詞、動詞、形容詞...があって」とトップダウンに勉強はしません。ですからこの章は初めて読む場合はサラリと目を通す程度でかまいません。
2.1 C言語の成り立ち
リストtest07.cはごく一般的なC言語のプログラムです。ソースリストやソースプログラムとも呼びます。test07.cを例にC言語の成り立ちを学びましょう。
リスト test07.c
#include<stdio.h> main() { int i,j; for( i=1 ; i <= 10 ; i = i+1 ){ j = i * 2; printf("%d\n" , j); } printf("end"); }
●プリプロセッサ
C言語はコンパイラ言語です。ですからC言語で書かれたソースプログラムが最終的にはマシンが実行可能なマシン語のプログラム、つまり実行ファイルに変換されます。C言語の場合、他の言語と異なる点は、プリプロセッサと呼ばれる、前処理があることです。このプリプロセッサ機能によりC言語自体の言語仕様を小さくしたままで機種依存や可搬性を高めること可能にしています。プリプロセッサの機能をつかって様々な置き換えや定義をすれば、確かにプログラムは読みやすくなりますが、細かなトラブル等が発生すると結局、組み込まれるヘッダーファイル等を覗かねばなりませんので乱用は禁物です。
リスト test07.c ではプログラムの初めにある #include <stdio.h> によってstdio.h と呼ばれるヘッダファイルがその行の位置に挿入されます。ヘッダファイルは stdio.h 以外にも多数準備されていて、これらのヘッダファイルはコンパイラのインストールされたディスクの中のincludeといったディレクトリにまとめて置かれています。しいていえばワープロの単文登録や決まり文句集といったところです。こららのヘッダファイルに書かれてある定義等によって、たとえばtest07.cではリスト中の関数printf()の宣言、つまり利用するための準備が行われます。
●C言語の構成要素
C言語の構成は以下のようになります。
○C言語は関数の集まりで構成されます。
○関数は文で構成され名前を付けて定義されます。
○文は特定の文や式で構成されます。
○式は定数や変数、演算子等で構成されます。
○変数は関数の初めに名前を付けて宣言して使用します。
これで終わりです。いたって簡単で明快です。それではここで出てきた「関数」「文」「式」について説明します。
[関数]
関数はユーザー(プログラマー)が定義するユーザー関数とあらかじめ用意されているライブラリー関数の2種類があります。リスト1のmain関数はユーザー関数です。ユーザーが中身を記述します。つまりプログラムします。ただしmain関数にかぎってはユーザー関数であってもかってに名前をつけることができません。リスト1の中のprintf はライブラリー関数です。コンパイラにライブラリとして付属してきます。
[文]
リストの
for( i=1 ; i <= 10 ; i = i+1 ){
j = i * 2;
printf("%d\n" , j);
}
は、これ全体で1つの文です。正確にいうと外からみると1つの文としてあつかえるということです。この文はfor文とよばれる特定な文です。for文は
for( 式 ; 式 ; 式 )
文
という構成をとります。とすると
{
j = i * 2;
printf("%d\n" , j);
}
も1つの文となります。{}でまとめられた部分をブロックと呼び1つの文として扱えます。
そして、ブロックの中の j = i * 2; と printf("%d\n" , j ); はそれぞれ1つの文です。
一般の文は
式 ;
となります。
[式]
ですから j = i * 2 は式ということになります。そして printf("%d\n" , j ) も式となります。後の式は不自然に感じますがC言語では値のとるものをすべて式として扱います。printf()は関数でした。関数は値を持つので単体でも式を構成できます。リストtest07.cでは
i=1 、 i <= 10 、 i = i+1 、 j = i * 2 、 printf("%d\n" , j) 、 printf("end")
がすべて式となります。
[宣言]
リストの4行目にでてくる int i,j; は宣言です。文とよくにていますが、文とは区別します。変数の設定や関数の引き数と値の型を決めます。int i,j; の場合、int型の変数をi と j という名前で1つずつ用意する、という意味になります。宣言は関数やブロックの初めにその関数やブロック内で使用する変数や関数について行います。
●C言語のトークン
C言語を構成する関数や文は個々のトークンつまり単語で組み立てられます。それらは、
識別子(名前)case enum register typedef
char extern return union
const float short unsigned
continue for signed void
default goto sizeof volatile
do if static while
更に各種コンパイラによって独自に拡張されてる場合があります。
[定数と文字定数]
数字と1字の文字です。リストの j = i * 2 の 2 です。
数字の場合10進数、16進数、8進数を区別するための約束があります。文字ではコントロール・コードを表すための約束があります。
定数は次のように指定することができます。
定 数 型 表 現 方 法
-----------------------------------------------------------------------------------------
整数定数 小数点をつけない。
10進数 数字をそのまま書く
8進数 0の後に数字を書く
16進数 0x , 0X の後に数字を書く
倍長整数定数 数字の後に l , L を書く
無符号定数 数字の後に u , U を書く
-----------------------------------------------------------------------------------------
浮動小数点定数 小数点をつける。
単精度浮動小数点整数 数字の後に f , F を書く
倍精度浮動小数点整数 @ 0x22 " 二重引用符
\? 0x3F ? 疑問符
\DDD 任意 任意 DDDは8進数
\xHHH 任意 任意 HHHは16進数
[文字列]
リストの printf("%d\n") の "%d\n" です。特殊記号を含む文字の並びを " でくくったものです。文字列は最初の文字のポインタつまり文字列の格納されるアドレスを返します。
[演算子]
その名のとうり計算を表すための記号です +、-、*、/ などですが、C言語では式と同様に意味が拡大されav[]の [] や *fp の * も演算子です。演算子は、以下のとおりです。
[ ] ( ) . -> ++ -- & * + - ~ !
sizeof / % << >> < > <= >= == != ^
| && || ?: = *= /= %= += -= <<= >>=
&= ^= |= ,
これらは扱う要素の数によって単項演算子、2項演算子、3項演算子に分けられます
2.2 数と演算
C言語でのデータの取り扱いについて説明します。これらは流れの扱い方と同様に言語の基本をなすもので、その言語のプログラミングに対する思想が最もよく反映しています。
2.2.1 数と文字の扱い
○3つのデータ型を覚えよう
C言語で取り扱うことのできるデータ型は図に示すように4〜5種類です。この中の char、int、double を理解すれば大半のプログラムが組み立てられます。C言語では、このデータの種類のことを「型」と呼びます。char は Characterの略、int は integerの略です。double は倍精度浮動小数の倍を表しています。この3つのは以下のように使い分けます。
char :文字、文字列に使用する
int :整数のデータ、フラグ、ループカウンタなど広範囲に使用する
double :浮動小数表現が必要なデータに使用する。
○double型を使う
double 型を使えば1/2などの計算が正しく行われます。またprintf関数を用いて表示する場合は%dでなく%fまたは%eを用います。
リスト test08.c
#include<stdio.h>
main()
{
double a,b,c,d,e,f;
a = 1;
b = 2;
c = 2147483647;
d = a / b;
e = a + c;
f = c * c * c * c;
printf( "%f %f %f %f\n" , d, c, e ,f);
printf( "%e %e %e %e\n" , d, c, e ,f);
}
実行結果
0.500000 2147483647.000000 2147483648.000000 21267647892944573000000000000000000000.000000
5.000000e-001 2.147484e+009 2.147484e+009 2.126765e+037
*1バイトは8ビット
●intは数専用、charは文字専用ではない
C言語では、データはメモリーに置かれる2進のデータと非常に近いかたちで扱われます。ですから、int型でも、char型でも同じように使えます。リスト09ではchar型変数を使ってループを制御してみます。
リスト test09.c
#include<stdio.h>
main()
{
char i;
for(i=0;i<10;i++){
printf("%d ",i);
}
}
<図> リスト1の実行結果
0 1 2 3 4 5 6 7 8 9
この例は使えるということの説明のためです。たとえ10回程度のカウントでも、普通はけちらずにint型を使います。C言語ではintとcharは文字と数の区別でなく扱うデータの大きさの違いを区別しています。
●文字の扱い
C言語では文字データはアスキーコードとして変数に記録されます。
その値は数として自由に演算できます。リスト2は a の文字コードを設定して、その次のコードと併せて表示します。printfを使って文字を表示する場合は %c を指定します。
<リストtest10.c>文字の取り扱い
#include<stdio.h>
main()
{
char c,d;
c = 0x61;
d = c + 1;
printf("%c %c", c, d);
}
アスキーコードを取り出す演算子として’(シングルコーティション)が有ります。リストtest11.cに’の使い方の例と実行結果を示します。BASIC言語からC言語に移行したときによくおきる間違いに”(ダブルコーティションと’との使用方法を混同することがあります。C言語では両者はまったく意味が違いますから注意して下さい。
<リスト test11.c>
#include<stdio.h>
main()
{
char
P
ASCIIコード表 ASCIIコードは8ビットASCIIと7ビットASCII があり、表は7ビットASCIIを示しています。 表の縦が下位4ビット、横が上位3ビットを表し ます。 例えば A は 41H(16進数)又は 4 * 16 + 1 = 65(十進数)となります。 |
2.2.2 演算子について
○単項演算子
+ 単項プラス - 単項マイナス ++ インクリメント -- デクリメント
~ ビットごとの補数 ! 論理否定 * 間接演算子 & アドレス演算子
○2項演算子
+ 2項プラス - 2項マイナス * 乗算 / 除算
% 剰余(余り) << 左シフト >> 右シフト
& ビットごとのAND | ビットごとのOR ^ ビットごとのXOR(排他的OR)
&& 論理AND || 論理OR
+= 和の代入 -= 差の代入 *= 積の代入 /= 商の代入
%= 剰余の代入 = 代入 <<= 左シフトの代入 >>= 右シフトの代入
&= ビットごとのAND代入 |= ビットごとのORの代入 ^= ビットごとのXORの代入
< より小さい > より大きい <= 小さいか等しい >= 大きいか等しい
== 等しい != 等しくない . 直接要素選択子 -> 間接要素選択子
○3項演算子
? : 条件演算子
個々の演算子の働きをまとめておきます。
|
|
●代入演算子
代入演算子は以下のとおりです。
演算子 例 意味 演算子 例 意味
--------------------------------------------------------------------------------------------------------------
= x = y x = y += x += y x = x + y
-= x -= y x = x - y *= x *= y x = x * y
/= x /= y x = x / y %= x %= y x = x % y
>>= x >>= y x = x >> y <<= x <<= y x = x << y
&= x &= y x = x & y |= x |= y x = x | y
^= x ^= y x = x ^ y
●インクリメント/デクリメント演算子
インクリメント( ++ )は1加えます。デクリメント( -- )は1引きます。例外にポインタ変数などがあります。ポインタ変数の場合ポインタが指すデータの型のサイズ分だけの増減が行われます。この演算子を変数の前に書くと、式が評価される前に値が変更されます。また、後に書くと式が評価されてから値が変更されます。
例
--------------------------------------------------------------------------------------------------------------------
int x,y; int x,y;
x = 1; x = 1;
y = ++x; y = x++;
--------------------------------------------------------------------------------------------------------------------
x ,y ともに 2 になります。 x は 2、y は 1 になります。
--------------------------------------------------------------------------------------------------------------------
|
|
●カッコ演算子
関数呼び出し、または関数引数を示します。
●アドレス演算子/間接参照演算子
アドレス演算子 & はオペランドのポインタを返します。間接参照演算子 * はポインタの示す内容を返します。
●メンバ選択(構造体アクセス)演算子
構造体や共用体のメンバを指定します。
・直接メンバ選択子 . の左辺式は構造体型か共用体型でなければいけません。
・間接メンバ演算子 -> の左辺式は構造体か共用体のポインタでなければいけません。
◆配列添え字演算子
配列の添え字を意味します。
◆三項演算子
条件に従い値を返します。式1が真なら式2を返し、偽なら式3を返します。C言語では0以外の値を真、0を偽として扱います。
式1 ? 式2 : 式3
◆sizeof演算子
与えられた式や型のバイト数を返します。
sizeof 式
sizeof( 型 )
◆順次演算子(カンマ演算子)
式の評価の順を指定します。
式1 , 式2
式1を評価してから式2を評価します。
例
---------------------------------------------------------------------
int x ;
x = (1, 2);
--------------------------------------------------------------------
x には 2 ゴシック" SIZE="2">main()
{
int x,y,z;
x = 65;
y = 0x42;
z = 'C';
printf("%d %x %c \n", x, x, x);
printf("%d %x %c \n", y, y, y);
printf("%d %x %c \n", z, z, z);
}
実行結果
65 41 A
66 42 B
67 43 C