C ⾔語の⽂法まとめ
ver. 2018/04/24
C ⾔語の基本事項
⼤⽂字と⼩⽂字は区別される。通常⼩⽂字で書く。
⽂の終わりには;を⼊れる/**/で挟まれた領域はコメント⽂としてコンパイル時には無視される。

⼀⾏が⻑くなって複数⾏にまたがる場合は;を⼊れずに改⾏
a = 1.0 + 2.0 + 3.0 + 4.0 +5.0 + 6.0 + 7.0 + 8.0 +9.0 + 10.0;○プログラムの基本構造#include<ヘッダファイル名.h>int main(){
宣言文 (変数宣言など)
実行文}

プログラムは main 関数として実⾏される。
ヘッダファイルには、プログラム内でライブラリ関数などを⽤いる場合に読み込む。数値計算で必要となるのはstdio.h : ⼊出⼒関数(printf, scanf, fopen など)
math.h : 数学関数 (sin, cos, pow, exp など)
stdlib.h : 整数型絶対値(abs)complex.h : 複素数型宣⾔、複素関数 (cexp, creal, cimag など)

型
変数型

記述⽅法

整数型
単精度実数型
倍精度実数型

int
float
double1複素数型
倍精度複素数型
論理型
文字型

float complex
double complex
boolchar(complex.h のインクルードが必要)(complex.h のインクルードが必要)(stdbool.h のインクルードが必要)

変数名︓英数字とアンダーラインが使える。英字かアンダーラインから始まる名前。
変数の宣⾔例
int a;
double b,c;double d = 0.0; /* 初期値入力 */double complex dt1;
const int a = 100; /* プログラム中で値を変更しない変数(定数)には const 修
飾子をつける */⽂字型変数の宣⾔例
char a = "a"; /* 長さ 1 文字の文字列 */char a[5] = "abcd"; /* 長さ 4 文字の文字列。最後にヌル文字\0 が必要なので確保する配列の大きさは 5 */変数型について
整数型：4 バイト(32 ビット), 2 進数でメモリに格納。最大値 231-1 まで
単精度実数型：4 バイト、10-38~1038, 約 7 桁の精度(符号、指数と仮数部に格納)
倍精度実数型：8 バイト、10-308~10308 約 16 桁の精度
単精度複素数型：8 バイト、実部と虚部が単精度実数型
倍精度複素数型：16 バイト、実部と虚部が倍精度実数型
論理型： true または false
実数と複素数型では基本的に倍精度のものを使う。
○四則演算(+, -,*, /)、累乗はない。(*で何度もかけるか、数学関数の pow を使う)
同じ型の演算は同じ型となる。(整数型/整数型は整数型)
a = 5 / 2;/* a は 2 となる。 2.5 にしたい場合は 5.0/2.0 とする */違う形の演算は型変換が⾏われる(整数と実数の演算は実数に、実数と複素数の演算は複素数に)
a = 4*4*4;/* 4 の三乗 */a = pow(4.0,3.0); /* 4 の三乗、入力も出力も倍精度実数型 */2

○代⼊⽂
変数に値を代⼊するには=を使う(数学の等号ではない)
a = 5 / 2.0;i = i + 5;i += 5;/* 倍精度実数型の a に 2.5 を代入 *//* i を 5 増やす。(再帰代入) *//* ともかける */○インクリメント・デクリメント演算
i=i+1;
i=i-1;

はは前置形︓++i;

i++;
i--;

あるいはあるいは++i; とかける。
--i; とかける。

--i;

加算・減算された後に結果が実⾏される。
基本例：i=0;
printf("%d", a[++i]);とすると i に 1 が代入され、a[1]が表示される。
後置形; i++;i--;

基本例：i=0;
printf("%d", a[i++]);とすると a[0]が表示された後 i に 1 が代入される○for ⽂の使い⽅
for( 式 1; 式 2; 式 3) { 繰り返し⽂ }式 1 を実⾏(初期化)、式 2 の条件を判定、満たされていれば繰り返し実⾏⽂を実⾏、式 3 を実⾏してから式 2 の条件判定に戻る
基本例１（sum（初期値 0）に N 回 1 を⾜す）
sum = 0;for( i=0; i<N; i++){sum = sum + 1;}
基本例２（sum（初期値 0）に i が 1〜N まで増える間、3 回ごとに i を⾜す）
sum = 0;for(i=0;i<N;i+=3){
sum = sum + i;}
補⾜説明︓

インクリメントfor ⽂のカウンタはこの場合は 3 つずつ増えて⾏く。つまり、i=1, 4, 7, 10, …の様3に増えて⾏く事に注意。

○if ⽂の使い⽅
基本例１（i の値が 0 の時は 0 を、１以上の時は 1 を、それ以外（つまり負の値）の時は-1を加える）
if (i==0){i = i;}else if (i >= 1){i++;}else{i--;}
補⾜説明︓

]

A==B
A!=B
A>=B
A>B
A<=B
A<B

関係演算⼦

:A が B と等しい時（A=B）に真:A が B と等くない時（A≠B）に真:A が B 以上の時（A≥B）に真:A が B より大きい時（A>B）に真:A が B 以下の時（A≤B）に真:A が B より小さい時（A<B）に真○if ⽂による for ⽂ループの制御
基本例 1

for ⽂で終了条件を書かない (break でループを抜ける)
for(x=0.1; ; x+=0.1){
y = x*x;
printf("%f %f\n", x, y);if ( x > 1.0)
break; /* x>1 なら for ループから出る */}条件が満たされないとプログラムは終了しないので端末から Ctrl-C で強制終了する。
基本例 2 特定の条件のときはそれより下の for ⽂内を実⾏しない(conitnue で for ループの頭に戻る)
for(i=0; i<N; i++){if ( i == 7)4continue; /* i が 7 のときは戻って i=8 の処理に移る。*//* ここに i が 7 以外のときの計算を書く */}○標準⼊出⼒(scanf, printf ⽂の使い⽅)
基本例 1（コマンドラインから hoge を読んで、hoge をディスプレーに出⼒）
scanf("%d", &hoge);
printf("%d", hoge);
補⾜説明︓

⼊出⼒の型を明⽰。
%d整数型, %f 実数型, %lf 倍精度実数型

scanf のときは読み込みたい変数名の前に&をつける(変数のアドレス)
printf ⽂で改⾏は¥n
基本例 2(コマンドラインから倍精度実数 hoge1 と hoge2 を読んで両⽅を出⼒
scanf("%lf %lf", &hoge1, &hoge2);
printf("hoge1 = %f hoge2 = %f\n", hoge1, hoge2);○ファイル⼊出⼒
基本例（"ファイル名 1 を読み込み専⽤で開き、ファイル名 2 を書き込み専⽤で開き、それぞれのファイルにデータを⼊出⼒する）
FILE *fp1, *fp2; /* FILE 型ストリーム、stdio.h で定義されている */fp1=fopen("ファイル名 1", "r"); /* ファイルを開く */if (fp1==NULL){ /* ファイルが開けなかった場合エラー処理 */printf("fp1 file open error\n");return(-1);}
fp2=fopen("ファイル名 2", "w"); /* ファイルを開く */if (fp2==NULL){ /* ファイルが開けなかった場合エラー処理 */printf("fp2 file open error\n");return(-1);}
fscanf(fp1, "%lf", &hoge);/* fp1 ストリームから倍精度実数 hoge を読み込

fprintf(fp2, "%f\n", hoge);/* fp2 ストリームに倍精度実数 hoge を書き込む

む*/*/
fclose(fp1); /*ファイルを閉じる */5fclose(fp2);

補⾜説明︓
fopen の読み書きのモード:
r : 読み込み
w: 書き込み
a: 追加書き込み(ファイルが存在する場合ファイルの末尾に書き込む)○配列（ベクトル）の扱い⽅
型宣⾔
基本例
double a[5], b[4][3]; /* a は 5 つの要素を持つ配列、b は 4x3 の行列 */配列のラベルは 0 から始まる。a[5]として定義されている場合、5 つの要素はa[0], a[1], a[2], a[3], a[4]となる。
配列を定義
初期値設定
double l[5]={0.,0.,0.,0.,0.}; /* 配列 l の成分がすべて 0 */int l2[5] = {1,2,3,4,5}; /* 配列 l2 の各要素の初期値を設定 */基本例（n 次元配列 a の全要素に 0 を代⼊）
ifor(i=0; i<n; i++){a[i] = 0.0;}
補⾜説明︓当然、0 以外の要素の代⼊・演算も可能

また、異なる配列の違う添字を持つ要素の代⼊・演算も可能
for(i=0; i<n; i++){a[i] = b[i+3];}
この時、b の配列の⼤きさは n+3 より⼤きくないと不可宣⾔時に配列の⼤きさに変数を使いたい場合は const 修飾⼦を使う
6

const int n=100;
double a[n], b[n], c[n];コンパイル時に配列の⼤きさが決まらない場合(動的確保)
int n;
double *a;scanf("%d", &n); /* 例えば実行時に配列のサイズとなる整数型を読み込む*/
a = malloc(sizeof(double)*n); /* a にサイズ n の実数型配列を確保する *//* ここで計算をする */free(a); /* a の配列をメモリから開放する */多次元配列の場合
int n,m;double *a;scanf ("%d %d", &n, &m);
a = malloc(sizeof(double) * n * m); /* 一次元配列として確保 */for (i=0; i<n; i++){for(j=0; j<n; j++){a[i*m+j] = .....; /* 添え字を 1 次元化する。[i][j]成分は[i*m+j]として参照する */}}free(a);○⾏列の扱い⽅
基本例（n×n ⾏列 b の全要素に 0 を代⼊）
ij

for (i=0;i<n;i++){for(j=0;j<n;j++){b[i][j]=0.0;}}
補⾜説明︓２重ループの構造上、内側のループが優先的に変化する。
C ⾔語では多次元配列は
b[0][0], b[0][1], b[0][2], ... b[0,n-1], b[1][0], b[1][1], b[1][2], ...の順番にメモリに格納される (Fortran では逆)。
この順に演算をしたほうがキャッシュミスが少なくなる。

7

○型変換
cast 演算⼦を使う[(型名) 式]。整数の実数化、実数の整数化
基本例（i の値を ai と実数化、a の値を ia と整数化）
ai=(double) i;/* i を倍精度実数型に変換 */ia=(int) a;/* a を整数型に変換 */複素数の実部、虚部取り出し (creal, cimag)
基本例
rez = creal(z); /* 複素数 z の実部を(倍精度)実数型 rez に代入 */imz = cimag(z); /* 複素数 z の虚部を(倍精度)実数型 imz に代入 */２つの実数を実部と虚部とする複素数を作る
z = 2.0+I*1.0;/*複素数に特定の数値を代入( z に 2.0+i を代入) */虚数単位は I として complex.h で定義されている○書式 (printf, fprintf)
基本例
サイズ指定なし

サイズ指定

整数%d%5d

実数%f%15.10f (全桁数 15 で 10 桁⼩数点以下)

⽂字%c⽂字列%s%10s (10 桁の⽂字列)

scanf, fscanf で読み込むときは整数%d倍精度整数%ld

単精度実数%f

倍精度実数%lf(5 桁の整数)編集記述⼦の種類○組み込み関数(倍精度実数⽤)
数学関数
8math.h

名称

数学的math.h

名称

数学的log(x)

⾃然対数

log (x)elog10(x)常⽤対数log (x)exp(x)

指数ex

sqrt(x)平⽅根√xsin(x)正弦sin(x)cos(x)

余弦

cos(x)

tan(x)

正接

tan(x)

asin(x)逆正弦arcsin(x)acos(x)逆余弦

arccos(x)atan(x)逆正接

arctan(x)atan2(y,x)

逆正接2arctan(y/x)

sinh(x)双曲線正弦sinh(x)cosh(x)双曲線余弦

cosh(x)tanh(x)双曲線正接tanh(x)fmin(x,y)

最⼩値

min(x,y)fmax(x,y)

最⼤値

max(x,y)pow(x,y)累乗xyfabs(x)

絶対値|x|

10

複素数関数
FORTRAN式

名称

数学式

FORTRAN式

名称

数学式

creal(z)実部

Re z

cimag(z)虚部Im zconj(z)

複素共役z*

carg(z)偏⾓Arg zcexp(z)指数ezcabs(z)

絶対値|z|

clog(z)

⾃然対数

log z

csqrt(z)平⽅根√zcsin(z)

正弦

sin(z)

ccos(z)

余弦

cos(z)

ctan(z)

正接tan(z)

casin(z)逆正弦arcsin(z)cacos(z)逆余弦arccos(z)catan(z)逆正接arctan(z)補⾜説明︓⾓度の単位はラジアン単位なので注意（180°=πラジアン）○論理演算if ⽂の中で、⽐較演算⼦や論理型の変数と共に⽤いられる。
論理演算⼦

意味 & 意味!

以外! a==b&&

かつ

a==b && b==c||もしくはa==b || b==c

例︓
9

if(a==B && b>=c)if(!(a==b))if((a==b) == (b>=c))：a と b が等しく、b が c より大きい時真：a と b が等し無い時真(a!=b と同じ)
：a と b が等しく、b が c より大きい時真、またa と b が等しく無く、b が c 以下の時真○関数
関数を定義することで組み込み関数と同じように使うことができる。
関数の値は return ⽂で返す。
基本例 1︓ f(x) = 4x3 - 5x を関数 func として定義して main 関数から呼び出す
関数 func が main 関数より前に読み込まれる場合#include<stdio.h>
double func(double x){
double y;y = 4.0*x*x*x - 5.0*x;
return(y);}int main(){double x;for(;;){
printf("%f %f\n", x, func(x));
x +=0.1;
if(x>5.0) break;}}

基本例 2: 関数 func が main 関数の後に読み込まれる場合#include<stdio.h>
int main(){double x;
double func(double); /* 関数プロトタイプ宣言、main より手前でもよい */for(;;){
printf("%f %f\n", x, func(x));
x +=0.1;
if(x>5.0) break;}}10

double func(double x){
double y;y = 4.0*x*x*x - 5.0*x;
return(y);}○再帰
関数で⾃分⾃⾝を引⽤することを再帰という。漸化式の計算などに使える。
基本例(フィボナッチ数列)
int fibonacci(int n){
int fibo;
if( n<0 ) {fibo = -1;
return(fibo);}
if( n == 0 ) {fibo = 0;} else if (n == 1) {fibo = 1;} else {fibo = fibonacci(n-1) + fibonacci(n-2);}
return(fibo);}○関数での複数の値・配列の受け渡し
関数の戻り値は⼀変数なので複数変数あるいは配列の値を戻り値としてほしいときは引数に変数や配列のアドレスを渡し、関数の中でその変数の値を更新する。
基本例︓外積を計算#include<stdio.h>
int main(){double a[3], b[3], c[3];void outerproduct(double [3], double [3], double [3]);a[0]= 6.0; a[1] = 3.0; a[2] = 4.0;b[0]= 3.0; b[1] =-2.0; b[2] =-4.0;
11

outerproduct(a, b, c);/*配列のアドレスを渡す */printf("%f %f %f\n", c[0], c[1], c[2]);return 0;}
void outerproduct(double a[3], double b[3], double c[3]){/* double *a, double *b, double *c でもよい */c[0]=a[1]*b[2]-a[2]*b[1];c[1]=a[2]*b[0]-a[0]*b[2];c[2]=a[0]*b[1]-a[1]*b[0];
}

○ポインタ
準備中
○コンパイル$ gcc プログラムソースファイル.c-o 実行ファイル名

コンパイルオプション-O0, -O1, -O2, -O3 : 最適化オプション-lm 数学関数を使うとき-Wall : 全てのコンパイル時の警告メッセージを出⼒-Wuninitialized : 初期化されていない変数を検出-pedantic : 標準外の機能利⽤を警告○デバッグ
⽂法以前のチェック事項① 変数の打ち間違いは無いか︖

︔の打ち間違えで︓や , を使っていないか︖② scanf を使うときは読み込む変数の前に&をつけているか︖書式指定は正しいか︖③ 配列の⼤きさが、定義された範囲を超えていないか︖④ for ⽂や if ⽂などがきちんと閉じているか︖⑤ emacs では正しくコーディングされているとタブを押したときに各⾏が整列する。
実践的なデバッグの⽅法
12

① ⾊々な所に printf ⽂を挿⼊し、途中結果、for ⽂の変数の増え⽅等をモニターする。
② /**/ でコメント化することでソースコードの保存や実⾏を⾶ばすことも可能。

③ for ループの変数がちゃんと受け渡されているかどうかチェックする。特に、配列の⼤きさを超える変数が受け渡されると、他のデータを破壊してしまうので要注意。
④ 配列にきちんとデータが読み込まれているかチェック。
⑤ 検索コマンドで、同じ変数がちゃんと検索されるかどうかチェック。
⑥ コンパイル時にデバッグオプションを追加

13