C言語

C言語、まずはこれだけ

このブログでは、主にC言語で書いたプログラムを使って解説しています。C言語に慣れていないかたのために、C言語の入門的な文法をまとめました。このまとめは、わたくしがこのブログでプログラムを書く時のガイドラインともなります。

残念ながら、説明やプログラムの例には後方で説明していることが含まれています。一通り目を通して、読み直していただけたらと思います。また、入門的な文法を超えた範囲について紹介するときは、以下のように記載します。

入門を超えた文法要素は、このように紹介します。

前提となる知識

基本は、宣言と定義

C言語のプログラムは、宣言と定義を記述していきます。Python などのスクリプト言語と異なり、実行するすべてのコードは、関数内に記述します。

ある程度の大きさのプログラムは、複数のファイルに分けてプログラムを書きます。その場合は、以下のように分けるとよいでしょう。

  • 宣言は、ヘッダファイルと呼ぶ拡張子が .h のファイルに記述します。
  • 定義は、拡張子が .c のファイルに記述します。

このブログでは、特別な記載がない限り、ひとつのファイルにすべてのプログラムを記述します。

コメント

コメントは、/* で始まり、*/ で終わります。複数行にまたがってコメントも作れます。

また、// という形式のコメントも使えます。これは、// 以降、行末までがコメントとなります。

// 形式のコメントは、C99 という規格から使えるようになりました。C90 という、それより古い規格では使えない形式ですが、現在の環境の多くは使えると考えてよいです。

関数

main 関数

プログラムを実行すると、main 関数が最初に動きます。main 関数の最後までコードが実行されれば、プログラムは終了して、システムに制御を戻します。このブログでは、プログラムが正常に終了したことを強調するために return 文で値 0 を指定することにします。

int main(void)
{
	/* program */

	return 0;
}

その他の関数

独自の関数を定義することができます。関数の名前の後ろのカッコ内に記載する変数で、呼び出し元と情報の交換ができます。関数は return 文に値を指定することで、戻り値を返すことができます。以下は、独自関数の定義と呼び出し例です。

int function(int data)
{
	return data + 1;
}

int main(void)
{
	int a;

	/* 関数 function を呼び出すことにより、a には2が代入される */
	a = function(1);

	return 0;
}

このブログでは、main 関数の前に独自関数の定義を記すことにしますが、一般的には、関数の宣言となるプロトタイプ宣言をヘッダファイルに書いて #inlcude するか、ファイルの冒頭に記載します。

変数

プログラムでは、数字や文字などのデータをメモに残して処理を進めます。このメモを変数と呼びます。変数には、型、参照できる範囲(スコープ)、寿命(いつ準備できて、いつ廃棄されるのか)などの属性がありますが、まずは型を中心に説明します。

値を設定するには、= を使う。

変数は、= を使って値を設定することができます。この値の設定は、変数の定義をするときでも、そのあとに実行するコードでも使えます。

整数型

整数の変数は int のあとに変数名を指定して定義します。int の変数には、-2147483648 (-231)から 2147483647(231-1)までの値が使えます。この範囲よりも大きな整数については、long long int のあとに変数名を指定して定義します。

以下の例では、int 型の変数 a と、long long int 型の変数 b を定義しています。

int main(void)
{
	int a;
	long long int b;

	a = 100;
	b = 1000000000000; 

	return 0;
}

実は、C言語では整数の大きさを厳密には決めていません。整数の大きさの規格定義や現実の運用については、次の記事をご覧ください。

C言語:整数の大きさのまとめ

配列

変数をいくつか組にして取り扱うことができます。これを配列と呼びます。注意としては、配列変数の定義では、要素の個数を指定します。使うときは、先頭の要素を [0] でアクセスします。このため、使うときに定義した個数を指定すると、1個あふれた場所に不正にアクセスします。

大きな要素を持つ配列の変数は、関数の外で定義すると覚えてください。初期値の指定の仕方は、コード例を参考にしてください。

/* 要素が10個の配列を定義する */
int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

int main(void)
{
	int a;

	a = array[0] + array[9]; /* 1 + 10*/
	/* 使えるのは、array[0] から array[9] */
	/* array[10] は使えないことに注意 */

	return 0;
}

文字型、文字列

文字の変数は char のあとに変数名を指定して定義します。この変数は、小さな整数としても使うことができます。

文字の変数の配列を、文字列として使うことができます。文字列は、ダブルクォーテーションで囲って指定することできます。注意としては、C言語の文字列は、文字列の終わりの目印とするために、値 0 の文字を追加しています。つまり、“hello” は、5個の要素を持つ文字の配列ではなく、6個の要素を持つ文字の配列になります。

char greeting[6] = "hello"; /* 配列は、6文字の要素を持つ */

演算子

変数や定数を使って、計算をすることができます。計算をするための記号を演算子と呼びます。C言語は、演算子が多いプログラミング言語ですが、よく使われるものを中心に紹介します。

四則演算と余り

+ は足し算、- は引き算、* は掛け算、/ は割り算の答え、% は割り算の余りを示します。算数の場合と同じく、足し算と引き算の優先順位は、残りの演算子より低くなります。

int main(void)
{
	int a = 10;
	int b = 3;
	int c;

	c = a + b;     /* c <- 13 */
	c = a - b;     /* c <-  7 */
	c = a * b;     /* c <- 30 */
	c = a / b;     /* c <-  3 */
	c = a % b;     /* c <-  1 */
	c = a + b * b; /* c <- 19 */

	return 0;
}

インクリメント/デクリメント演算子

++ で変数の値をひとつ増やします。-- で変数の値をひとつ減らします。この演算子は、変数の前につけても、後ろにつけてもよいです。

int main(void)
{
	int a = 8;
	int b = 5;

	++a; /* a <- 9 */
	--b; /* b <- 4 */

	return 0;
}

インクリメント演算子を変数の前に置くか、後ろに置くかで、インクリメントが発生するタイミングが異なります。前に置くと、変数をアクセスする前にインクリメントが発生します。後ろに置くと、変数をアクセスした後にインクリメントが発生します。次のコード例をみてください。

a = 3;
b = ++a; /* b <- 4 */
b = a++; /* b <- 3 */

代入演算子 +=*=

a += b; は、a = a + b; と同じです。a *= b; は、a = a * b; と同じです。

a += b; /* a = a + b */
a *= b; /* a = a * b */

制御構造

if 文、if-else 文

条件判断を行う場合には、if 文を使います。if 直後の(条件の式)が成立していたら、if のあとのブロックを実行します。もし、else ブロックがあれば、条件が成立しない場合に else ブロックを実行します。

	if (a % 2 == 0 ) {
		/* a が偶数のときの処理 */
	} else {
		/* a が偶数ではないときの処理 */
	}

if もしくは、else のあとの実行するコードは、ブロック(波カッコで囲む)である必要はありませんが、制御する範囲が分かりやすくなるため、ブロックにする(波カッコで囲む)と、覚えてください。

for 文

ループ変数がある繰り返しには、for 文を使います。次のカッコには、3つの記述をします。

for (初期化; 条件判断; 再初期化) { ループ本文 }

for 文に入ったときに「初期化」を一度だけ行い、「条件判断」が成立したときだけ、「ループ本文」を実行します。ループ本文内のコードをすべて実行したら、「再初期化」を行い、次の「条件判断」を行います。

int型の配列変数 array に値を代入するコードの例です。

	int array[10];

	/* ... */

	for (i = 0; i < 10; i++) {
		array[i] = i;
	}

for 文の「ループ本文」もブロックである必要はありませんが、制御する範囲が分かりやすいため、ブロックにすると覚えてください。

また、for 直後のカッコ内の3つの要素は省略可能ですが、セミコロン(;)は省略できません。

while 文

明確なループカウンタがないなど、for では表現しにくい繰り返しには、while 文を使います。while 直後の(条件の式)が成立していたら、while のあとのブロック(ループ本体)を実行します。ループ本体の実行が終わったら、もう一度(条件の式)を確認して、ループ本体を実行するのか、ループを抜けるのか判定します。

変数 sum の値が100未満の場合にループ本体を繰り返すコードの例です。

	while (sum < 100) {
		/* */
	}

等価演算子(==!=)、関係演算子(<<=>>=

条件判断や繰り返しの条件に使える演算子を紹介します。これらの演算子の結果は、条件が成立したときには 1 となります。成立しなかったときには 0 となります。

演算子意味
A == BA と Bの値が等しいとき値1、異なるとき値0になります。
A != BA と Bの値が異なるとき値1、等しいとき値0になります。
A < BA が B より小さいときに値1、それ以外の場合に値0となります。
A <= BA が B 以下のときに値1、それ以外の場合に値0となります。
A > BA が B より大きいときに値1、それ以外の場合に値0となります。
A >= BA が B 以上のときに値1、それ以外の場合に値0となります。

その他

文字列や整数の出力

stdio.h というヘッダファイルを #include して、printf という関数で画面に文字を出力することができます。printf の仕様は簡単ではありませんが、文字列と整数の出力方法だけ覚えておけば多くの場合に対応できると思います。

#include <stdio.h>

int main(void)
{
	int a = 10;
	char string[6] = "hello";

	printf("%d\n", a);       /* a の値10を出力 */
	printf("%s\n", string);  /* string の値を出力 */

	return 0;
}

typedef による型定義

unsigned long long int 型の変数を使う場合に、この型名は、長すぎるため、typedef を使って別の名前を定義します。以下が typedef の定義例で、この場合、ull を使って、unsinged long long int 型の変数が定義できます。

typedef unsigned long long int ull
ull a;

マクロ定数

マクロ定数という機能を使って定数にマクロ名を付けることができます。

以下の例では、配列の要素数に対して、N というマクロ名をつけて、配列変数を定義しています。なお、マクロ名は慣用で英字大文字を使います。

#define N 10
int array[N];

最後に

C言語の入門者向けの文法を紹介しました。C言語は、言語仕様が小さいプログラミング言語として知られていますが、その中から入門者向けにさらに文法を絞り込みました。また私がこのブログでC言語プログラミングに使う文法のガイドラインのつもりで記しました(ただし、プログラムの題材によって逸脱することも多いですが)。

入門者のみなさまの参考になることを願っています。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA