プログラミング演習第一
第1回目:プログラミング開発環境とコンパイル
A組 10/4(月) 1-2限
B組 10/5(火) 1-2限
担当:上瀧 剛(こうたき ごう)
http://www.cs.kumamoto-u.ac.jp/~koutaki/pukiwiki/
Mail:koutaki@cs.kumamoto-u.ac.jp
演習の目標:
C言語の文法の習得。
・関数(サブルーチン)
・配列、ポインタ、構造体
評価:
・レポート課題のみ。試験はありません。
・ただし、プログラミング方法論が不合格の場合、
本演習も不合格となります。
・2/3の出席が必要。レポート回収で出席を兼ねます。
・やむを得ず欠席する場合は必ず事前に連絡下さい。
事前連絡なしではレポートを受理しません。
スケジュール(予定)
何の役に立つのか:
卒業研究、就職活動、会社での業務、etc…
回 A組 B組 教科書の項目 内容 1 10/4 10/5 C言語プログラムの作成 C言語のやさしい入門 コンパイル・hello world 2 10/4 10/5 3 10/18 10/12 printf詳細、getc, make 4 10/25 10/19 変数とデータ型 変数、配列、文字列 5 11/8 10/26 演算子 四則演算、型キャスト、ビット 6 11/15 11/9 制御文 if, for, while, break, continue 7 11/22 11/16 コンソール入力 getchar, putchar 8 11/29 11/30 関数の作り方 関数宣言、グローバル宣言、 記憶クラス 9 12/6 12/7 10 12/13 12/14 ポインタ アドレス、ポインタ参照 11 12/20 12/21 12 1/17 1/11 ユーザが作成するデータ型 構造体、共用体 13 1/24 1/18 14 1/31 1/25 プリプロセッサ、標準ライブラリ、 ファイル入出力 実用プログラムプログラミング言語のタイプ
タイプ 備考 コード例 コンパイラ (ファイル) FORTRAN 最初の高級言語。 科学計算ソフト系(ex.行列演算、電 子状態計算)ではいまだに現役だっ たりします。 INTEGER I, J DO I=0, 10 j = j + i ENDDO F77, G77 (*.f,*.f77, *f90) C C++と並んで開発系で最もよく使われ る言語。 int i, j = 0;for(i = 0;i <= 10;i++) j = j + i; gcc, Visual C++(cl.exe) Boland C++ (*.c, *.h) アセンブラ 機械語に近い言語。SIMD並列処理 や高速処理が要求される箇所で、部 分的に使われることがある。
mov eax,dword ptr [ebp+0Ch] test eax,eax je 765CCDA1 mov ecx,dword ptr fs:[18h] Visual C++ Gas (*.asm) C++ おそらく開発系で最もよく使われる言 語。基本はC言語。 Int j = 0;
for(int i = 0;i <= 10;i++) j = j + i; Gcc, Visual C++(cl.exe) Boland C++ (*.cpp, *.cc) Java 開発系でよく使われる言語。基本はC 言語の文法に似ている。 Int j = 0;
for(int i = 0;i <= 10;i++) j = j + i;
Javac (*.java) 他にもいろいろあります
本日の演習内容
プログラミング開発環境とコンパイル
0. C言語でのプログラム作成手順
1.簡単なC言語のプログラム作成
2.コンパイルと実行
3.エラー、警告メッセージについて
4.まとめ
5.課題
0. C言語でのプログラム作成手順
C言語のプログラムソースを作成 (人間が読みやすい形式) コンパイル (コンピュータが理解できる形式に翻訳) 実行ファイル(バイナリ)出力 テキストエディタを使います。 Emacsやvi。Windowsだとメモ帳など。 翻訳プログラムをコンパイラといいます。 演習ではgcc(GNU C Compiler)というコンパイラを 使います。Windowsだと、VC++(cl.exe)などが あります。 実行ファイルを実行 ライブラリ (既にコンパイル済みの プログラムや関数群) リンク Windowsだとexeファイルに相当します。 リンクを行うプログラムをリンカと いいます。gccにはリンカ機能も 含まれています。 Windowsのパソコンを持っている人は、Cygwinというソフトをインストールすることで 本演習とほぼ同等の環境でgccを使うことができます。1.簡単なC言語のプログラム作成
Emacsを起動して以下のプログラムソースを作成して、ex1-1.cとして 保存してください。
>mkdir PEI
>cd PEI mv ex1-1.c PEI ・・・ファイルをPEIに移動 >emacs ex1-1.c &
#include <stdio.h>
int main(void){
printf(“hello, world!¥n”);
return 0;
2.コンパイルと実行
ソースを保存したら、以下のコマンドを実行してプログラムをコンパイルします。 問題なければ、次のプロンプト > が表示されます。 何かメッセージが出てくれば、どこかでプログラムを打ち間違えていますので 修正してください。 >gcc ex1-1.c > コンパイル 実行 >./a.out hello, world! > 以下のコマンドを入力して、先ほどコンパイルしたプログラムを実行します。 「hello, world!」と出てくれば成功です。プログラム解説
int main(void){ printf(“hello, world!¥n”); return 0; } メイン関数がここから{ hello, world!¥nという文字列を出力する 戻り値=0としてメイン関数を終了する メイン関数ここまで} ■ Cのプログラムはmain関数から開始されます。 関数の中身はカッコ{ }で閉じます。 ■文はセミコロン;で区切ります。 ■ printfは画面に文字列を出力する関数です。標準関数と呼ばれる関数です。 その宣言・定義は先のstdio.hに書かれています。 では、その処理を行う関数の中身は? →標準ライブラリ/usr/lib/libc.a の中に入っています。 おそらく、gccの作者がマシン語(画面出力というハードウェア制御が 入っている)などで作ってますので解読難。 ■main関数はint型(整数の値)を返さなければなりません。 ですのでreturn 0;が入っています。プログラム解説
int main(void){ printf(“hello, world!¥n”); return 0; } 文は字下げで見やすくします。 int main(void){ printf(“hello, world!¥n”); { int a; } return 0; }プログラム解説
int main(void){ printf(“hello, world!¥n”); return 0; } メイン関数がここから{ hello, world!¥nという文字列を出力する 戻り値=0としてメイン関数を終了する メイン関数ここまで}printf(“hello, world!¥n”);
文字列はダブルクォーテション“”で囲みます。
¥nは(あるいはバックスラッシュ/n)は改行の意味です。
他にも以下のようなものがあります。
printfは他にも機能がありますが、別途説明します。
¥n 改行 ¥t タブ ¥r 行の先頭に戻る ¥a ビープ音を 鳴らす ¥¥ ¥を表示 ¥” “を表示プログラム解説
#include <stdio.h> int main(void){ printf(“hello, world!¥n”); return 0; } テキスト出力関数printfを使うために、 printfが宣言されているヘッダファイルを読む。 stdio=Standard Input Outputの略#はプリアンブルの意味で、ヘッダファイルの内容を そのまま置き換える。
ではstdio.hはそもそもどこにあるのか? →/usr/include/の中にある。
>grep "printf" /usr/include/stdio.h
extern int fprintf (FILE *__restrict __stream,
extern int printf (__const char *__restrict __format, ...);
extern int sprintf (char *__restrict __s,
extern int vfprintf (FILE *__restrict __s, __const char *__restrict __format, extern int vprintf (__const char *__restrict __format, _G_va_list __arg); extern int vsprintf (char *__restrict __s, __const char *__restrict __format, extern int snprintf (char *__restrict __s, size_t __maxlen,
__THROW __attribute__ ((__format__ (__printf__, 3, 4))); extern int vsnprintf (char *__restrict __s, size_t __maxlen,
__THROW __attribute__ ((__format__ (__printf__, 3, 0)));
extern int vasprintf (char **__restrict __ptr, __const char *__restrict __f, __THROW __attribute__ ((__format__ (__printf__, 2, 0)));
extern int __asprintf (char **__restrict __ptr,
__THROW __attribute__ ((__format__ (__printf__, 2, 3))); extern int asprintf (char **__restrict __ptr,
__THROW __attribute__ ((__format__ (__printf__, 2, 3))); extern int vdprintf (int __fd, __const char *__restrict __fmt,
__attribute__ ((__format__ (__printf__, 2, 0)));
extern int dprintf (int __fd, __const char *__restrict __fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
extern int obstack_printf (struct obstack *__restrict __obstack, __THROW __attribute__ ((__format__ (__printf__, 2, 3))); extern int obstack_vprintf (struct obstack *__restrict __obstack,
__THROW __attribute__ ((__format__ (__printf__, 2, 0)));
プログラム解説
確認
>grep “printf” /usr/include/stdio.h
確かにある。
gccについて
>gcc ソースプログラムのファイル名 –o 出力ファイル名 –lライブラリファイル名 -o はOutputの略。このオプションを省略すると、a.outが出力ファイルとなる。 -l でライブラリファイル内の関数を出力ファイルにリンクします。 ・デフォルトでは –lc (libc.a:標準関数群)、-lm(libm.a:数学関数群)が リンクされます。 ・ライブラリファイルは/usr/libに置いてあります。通常、ここのディレクトリを gccは探しにいきます。 ・ライブラリファイルの中には沢山の関数が詰まっています。 ・gccは賢いので、ソースプログラム内で使われた関数だけを取り出して 自動的にリンクしてくれます。1.簡単なC言語のプログラム作成
以下のプログラムソースを作成して、ex1-2.cとして保存・コンパイル・実行してください。 /* 数値計算をするサンプルプログラム*/ #include <stdio.h> int main(void){ int nn; // 変数nnを宣言 nn = 4 + 5; // 4 + 5 の結果を変数nnに入れる printf(“%d + %d = %d¥n”, 4, 5, nn); // 結果を表示する return 0; }printf(“%d + %d = %d¥n”, 4, 5, nn);
%dは整数値を表示します。その整数値は、カンマ「,」の後に
それぞれ指定します。
1.簡単なC言語のプログラム作成
/* コメント文 */
// コメント文
/*************************************/
/* プログラム main.c by g.koutaki
*/
/* 2010.10.3 ver.1 */
/*************************************/
/************************************
プログラム main.c by g.koutaki
2010.10.3 ver.1
************************************/
コメント文の例
/* と */ の間で囲まれた文をコメントにする。 途中で改行しても、その間はコメント扱いになる。 // 以降をコメントにする。改行するとコメントを抜ける。 C++からの仕様だが、Cでも使える場合が多い。3.エラー、警告メッセージについて
・エラー(error)
スペルミスや文法ミスでコンパイルが通らない状態。
言われた箇所を直せば基本的にすぐ直る。
・警告(warning)
エラーではないが、望ましくないコードである。
→プログラムは実行できる。が、致命的なバグの原因になる
可能性があるので、なるべく警告は出さないように努める。
・バグ(bug)
エラーも警告もないが、プログラムがとまったり、望ましくない
結果が得られる。忌わしき事態。バグ取りは、ソフトウェア開発
でもっとも時間を要する作業。
3.エラー、警告メッセージについて
例)わざとエラーを出してみる。 >cp ex1-1.c ex1-3.c としてファイルをコピー。以下のように変更してみる。 #include <stdio.h> int main(void){ printf(“hello, world!¥n”); return 0; // } 次のようなエラーが出る。 >gcc ex1-3.cex1-3.c: In function „main‟:
ex1-3.c:6: error: expected declaration or statement at end of input
main関数ないでエラーがある。関数の終端がない。 // はコメント文の意味。この行は無視されます。
3.エラー、警告メッセージについて
例)わざと警告を出してみる。以下、ex1-4.cを作成する。 #include <stdio.h> int main(void){ int a, b; b = 1 / 0; printf(“hello, world!¥n”); return 0; } 次のような警告が出る。 >gcc ex1-3.c -Wallex1-3.c: In function „main‟:
ex1-3.c:6: warning: division by zero ex1-3.c:5: warning: unused variable „a‟
警告をすべて出すようにオプション-Wallを指定
main関数のなかで変数aを宣言したが 一度も使っていない。
3.エラー、警告メッセージについて
例)わざとバグを出してみる。ex1-5.cとして保存する。 #include <stdio.h> int main(void) { int index; int data[100]; data[index] = 100; index = index + 1; return 0; } これを作った人はindexは0で初期化されていると 勘違いしていたとする。 次のようなにコンパイルは問題なく通るが、プログラムを実行すると強制終了する。 >gcc ex1-5.c –Wall > ./a.outSegmentation fault (core dumped) >
メモリ関連で深刻なエラーが発生! このdata[100]は配列変数です。別途、演習で 詳しく解説します。