C 入門
サンプルプログラム
#include <stdio.h>
void main(){
printf("HelloWorld.\n");
}
実行結果
HelloWorld.
#include
という記述は、ヘッダファイルと呼ばれるファイルを読み込むときに用いる宣言
".h"は、C言語のヘッダファイルの拡張子
printf("HelloWorld\n");
サンプルプログラム
#include <stdio.h>
void main(){
printf("123\n456\n789\n");
printf("シングルクオーテーション:\'ダブルクオーテーション:\"\n");
printf("\t円マーク\\\n");
}
123
456
789
シングルクオーテーション:'ダブルクオーテーション:"
円マーク\
書式指定
\nを、文字列の途中に入れると、途中に改行が入る
%sや、%dは後に","(コンマ)で区切った値を表示できる。
printf("イニシャルは、%cです。\n",'Y');
イニシャルはYです。
printf("%f + %f = %f\n",1.2,2.7,1.2 + 2.7);
1.200000 + 2.700000 = 3.900000
演算子
#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 = 7
5 - 2 = 3
5 * 2 = 10
5 / 2 = 2 余り 1
コメントの書き方は
/* */ ブロックコメント
// 行コメント
です。
変数と定数
#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 = 9
6 - 3 = 3
6と3の平均値 4.500000
代入
int a;//←変数の初期化(aという変数を使えるようにする)
a = 6;//←代入。(変数に値を入れる)
初期化
※変数の宣言をする場所ですが、必ず{}の先頭の部分で行わなくてはなりません。
※上記のルールはC++では撤廃されています。
int a = 6;//← 変数の宣言と同時に値を代入(初期化)
変数のルール
- 使用できる文字は半角の英文字(A~Z,a~z)、数字(0~9)、アンダーバー(_)。(例:abc、i、_hello、num1など)
- 変数名の最初の文字を数字にすることは出来ない。必ず英文字およびアンダーバーからはじめること。(例:a123 → ○ 123a → ×)
- 英文字の大文字と小文字は別の文字として扱われる。(例:ABCとabcは違う変数とみなされる。)
- 規定されているC言語の予約語を使ってはいけない。
予約語
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=a+1; |
-= |
a-=1; |
a=a-1; |
*= |
a*=2; |
a=a*2; |
/= |
a/=2; |
a=a/2; |
%= |
a%=2; |
a=a%2; |
変数の型変換(キャスト)
i2 = (int)d2;
e2 = (double)j2;
分岐処理
C言語ではif(イフ)と、switch(スイッチ)という命令が用意されています。
IF文のサンプルプログラム
#include <stdio.h>
void main(){
int a;
printf("数値を入力:");
// キーボードから整数を入力
scanf("%d",&a);
// 入力した値が、正の数かどうかを調べる
if(a > 0){
printf("入力した値は、正の数です。\n"); // 正の数だった場合に実行
}
}
数値を入力:5
入力した値は、正の数です。
負の数だった場合の処理を作りたいときの
if(/*条件式*/){
//処理①
}else{
//処理②
}
0の場合などの複数条件を作成したい場合は
※②の else if は何度も書ける
if(/*条件式①*/){
//処理①
}else if(/*条件式②*/){
//処理②
}else{
//処理③
}
if文のネスト
if文の中にif文が書ける
if(/*条件式①*/){
if(/*条件式②*/){
//…
}
}
論理演算子
&& |
論理積(ろんりせき) | AND(アンド) | a == 0 && b == 0 // aが0かつ、bが0ならば |
` | ` | 論理和(ろんりわ) | |
! |
否定(ひてい) | NOT(ノット) | !(a == 0) // a==0でない場合、真となる |
if文ではなく値が固定されているのであればswitch文を使う
defaultはどの条件にも当てはまらない場合を示しています。
switch(/*値*/){
case /*値①*/:
//処理①
break;
case /*値②*/:
//処理②
break;
//・・・
default:
//処理③
break;
}
繰り返し処理
for文
サンプルプログラム
#include <stdio.h>
void main(){
int i;
for(i = 1;i <= 5;i++){
printf("%d ",i);
}
printf("\n");
}
1 2 3 4 5
for ( /*初期化処理*/ ; /*条件式*/ ; /*増分処理*/ ){
//処理
}
forの二重ループ
サンプルプログラム
#include <stdio.h>
// forの二重ループ
void main(){
int i,j;
for(i = 1; i<= 2; i++){
for(j = 1; j <= 3; j++){
printf("%d+%d=%d ",i,j,i+j);
}
printf("\n");
}
}
1+1=2 1+2=3 1+3=4
2+1=3 2+2=4 2+3=5
while文
サンプルプログラム
()の中の条件が成り立っている間は繰り返し処理が行われる
#include <stdio.h>
// iを用いたループ
void main(){
int i = 0;
while(i <= 5){
printf("%d ",i);
i++;
}
printf("\n");
}
0 1 2 3 4 5
whlie(/*条件式*/){
//処理
}
do~while文
#include <stdio.h>
// iを用いたループ
void main(){
int i = 0;
do{
printf("%d ",i);
i++;
}while(i <= 5);
printf("\n");
}
0 1 2 3 4 5
do{
//処理
}whlie(/*条件式*/);// ← whileの後にセミコロンがついている。
while文との違いは
仮に条件式を満たしていなくても最低限1度は処理が実行される
というところです。
無限ループ
while(1)とすると、基本的に処理は無限に繰り返されます
ただ、無限ループでも、break(ブレイク)があると、ループから出ることができます。
サンプルプログラムであったのは、入力した値が○以上だったら終了するというのがあった。while(1)とif文で構成
配列変数
変数を複数定義する場合は配列を使用する
サンプルプログラム
#include <stdio.h>
void main(){
// サイズ3の配列変数の宣言
double d[3];
double sum,avg; // 合計値、平均値を入れる変数
int i;
// 値を代入
d[0] = 1.2;
d[1] = 3.7;
d[2] = 4.1;
sum = 0.0;
for(i = 0; i < 3; i++){
printf("%f ",d[i]);
sum += d[i];
}
printf("\n");
avg = sum / 3.0; // 平均値の計算
printf("合計値:%f\n",sum);
printf("平均値:%f\n",avg);
}
1.200000 3.700000 4.100000
合計値:9.000000
平均値:3.000000
配列の数え方はちょっと複雑
この場合箱は3つあるが取り出す場合の数字は「0,1,2」の3つになる
double d[3];
配列の宣言と初期化を同時に
int n[] = { 5,4,3,2,1 };
int n[] = { 5,4,3,2,1 };
//↓ この処理は、以下の処理に相当
int n[5];
n[0] = 5;
n[1] = 4;
n[2] = 3;
n[3] = 2;
n[4] = 1;
scanf("%s",s3);// 文字列の入力
scanf()で整数値を入力するときには、"で囲まれた部分に、%dと書きました。しかし、文字列の場合は、%sとなります。
多次元配列
#include <stdio.h>
void main(){
int a[3][4];
int m,n;
// 二次元配列に値を代入
for(m = 0; m < 3; m++){
for(n = 0; n < 4; n++){
a[m][n] = m+n;
}
}
// 成分の表示
for(m = 0; m < 3; m++){
for(n = 0; n < 4; n++){
printf("%d ",a[m][n]);
}
printf("\n");
}
}
0 1 2 3
1 2 3 4
2 3 4 5
関数
同じ処理を何度も書く場合は関数を使う。
#include <stdio.h>
// 平均値を求める関数の定義
double avg(double l,double m){
// 引数l,mの平均値を求め、rに代入する。
double r = (l + m) / 2.0;
return r;
}
void main(){
double d1,d2,d3;
double a = 1.2,b = 3.4,c = 2.7;
// 同じ計算が3回(関数を呼び出して計算)
d1 = avg(a,b);
d2 = avg(4.1,5.7);
d3 = avg(c,2.8);
printf("d1 = %f,d2 = %f,d3 = %f\n",d1,d2,d3);
}
d1 = 2.300000,d2 = 4.900000,d3 = 2.750000
戻り値の型 関数名(引数の型 引数1,引数の型 引数2,・・・,引数の型 引数n)
{
処理
return 戻り値; ← 省略されることもある
}
関数には、好きな名前を付けることができますが、予約語を用いることはできない。
引数と戻り値
引数は受け取る数字で
戻り値は吐き出す数字です
プロトタイプ宣言
という方法もある
#include <stdio.h>
// 関数avgのプロトタイプ宣言
double avg(double,double);
void main(){
double d1,d2,d3;
double a = 1.2,b = 3.4,c = 2.7;
// 同じ計算が3回(関数を呼び出して計算)
d1 = avg(a,b);
d2 = avg(4.1,5.7);
d3 = avg(c,2.8);
printf("d1 = %f,d2 = %f,d3 = %f\n",d1,d2,d3);
}
// 平均値を求める関数
double avg(double l,double m){
// 引数l,mの平均値を求め、rに代入する。
double r = (l + m) / 2.0;
return r;
}
最初に宣言だけして、定義は後ろに書く。
上記のコードはdouble型だが、型なしで宣言できる。引数に型をなしにもできる。
void line(void);
※ほとんどの場合は引数が(void)の場合は省略される。
※また引数のない関数はreturn;が省略される。
グローバル変数・ローカル変数
- 関数内で定義されている変数を、ローカル変数
- プログラムの先頭で定義されており、どこで呼び出しても同じ変数を、グローバル変数と言います。
※グローバル変数はプログラム全体でただ一つだけ、なので名前の重複は許されません。
ファイル分割
cには、".h"(ヘッダファイル)と、".c"ファイル(ソースファイル)があります。
#ifndef _CALC_H_
#define _CALC_H_
// 関数avgのプロトタイプ宣言
double avg(double,double);
#endif // _CALC_H_
#include "calc.h"
// 平均値を求める関数
double avg(double l,double m){
// 引数l,mの平均値を求め、rに代入する。
double r = (l + m) / 2.0;
return r;
}
#include <stdio.h>
#include "calc.h"
void main(){
double d1,d2,d3;
double a = 1.2,b = 3.4,c = 2.7;
// 同じ計算が3回(関数を呼び出して計算)
d1 = avg(a,b);
d2 = avg(4.1,5.7);
d3 = avg(c,2.8);
printf("d1 = %f,d2 = %f,d3 = %f\n",d1,d2,d3);
}
冒頭に出ている#ifndef、#define、#endifは、マクロと言います。
alc.c、calc.hでインクルードされます。そのため、1回目は良いのですが、2回目のインクルードでこの間で定義されているプロトタイプ宣言が二回定義されることになり、コンパイルエラーになります。それを回避するために行っている
多分
1回目のインクルードで
double avg(double,double);
2回目のインクルードで
double avg(double l,double m){
//.
}
と同じ関数を2度使っているからコンパイルエラーになるがそれを回避するためのものだと思う。
#include
の使い分け
.hファイルの読み込みは、ダブルクオーテーションで 行います。
関数の定義の部分が、ライブラリファイル(.lib)など、すでにコンパイルされているものに関しては、<>でヘッダファイルを読み込む。
今回はヘッダファイル・ソースファイルは1つですが、開発規模によっては複数インクルードすることがあります。
複数に分割されたヘッダファイル・ソースファイルがどのようにしてマシン語に変換されているのかを理解しましょう
Cコンパイラの仕事は、ソースファイルを最終的に実行ファイルに変換することその仕事には3つのプロセスがある。
①プリプロセッサ
プリプロセッサは、ソースコードに一定の規則に従って処理を加えます。これによって、各ソースファイルおよび #includeや、#defineといったような、マクロの処理をするのが段階です。一般に、こういった命令をディレクティブと呼びます。この段階で行われるのは、いわばコンパイルの前処理といったところです。
②コンパイラ
プリプロセッサで処理されたコードを機械語に翻訳するのが、コンパイラの役割です。ただ、ここでは実行可能な形でのファイル ではなく、obj(オブジェ)ファイルもしくは、オブジェクトコードと呼ばれるファイルが形成されます。
オブジェクトファイルは、機械語に変換されたコードの断片の集まりであり、これらが最終的につながる(リンク)されることにより、 実行可能なファイルになります。
③リンカ
最終的に、コンパイラで作成された複数のオブジェクトファイルを一つにまとめて、実行ファイルを作るのがこの段階です。ただ、 Cの標準ライブラリなど、Cのソースコードだけでは足りない部分は、lib(ライブラリ)ファイルとして、ここで追加されます。 これらが統合されて、最終的な実行ファイルになります。
OSがウィンドウズの場合、実行ファイルには、「exe」という拡張子がついています。このファイルを、そのつづりから「エグゼファイル」などと 呼んだりします。
このように、プリプロセッサから、リンカまでの処理を通して、一般に、ビルドという言い方をします。