C プログラミング入門 総機1 (月1) 14: 発展事項 2014-07-13.

Slides:



Advertisements
Similar presentations
プログラミング 関数編 情報科学科. プログラミングにあたって C 言語では、 main 内に処理を記述 1000 行になるような大きなプログラムでは、 プログラム全体が何をしているのかを把握 することが困難になる 他人が見ると非常に理解しにくい 作成者であっても時が経てば内容を忘れて、他 人が見た時と同じ状況になる.
Advertisements

情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング入門2 第10回 動的な領域確保 情報工学科 篠埜 功.
第13回構造体.
データ構造とアルゴリズム 第10回 mallocとfree
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
アルゴリズムとプログラミング (Algorithms and Programming)
画像ファイル(ppm)の読み書き 画像データ用のメモリ確保・解放
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
第2回ネットワークプログラミング 中村 修.
12: コマンドライン引数 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
12: コマンドライン引数 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページ を開いておくこと
第8回 プログラミングⅡ 第8回
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
画像ファイル(ppm)の読み書き 画像データ用のメモリ確保・解放
第7回 条件による繰り返し.
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
プログラミング 2 ファイル処理.
プログラミング論 ファイル入出力
関数の定義.
プログラミング 4 記憶の割り付け.
プログラミング演習I 2003年6月25日(第10回) 木村巌.
04: 式・条件分岐 (if) C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 条件による繰り返し.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
プログラミング論 ファイル入出力
09: ポインタ・文字列 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
地域情報学 C言語プログラミング 第1回 導入、変数、型変換、printf関数 2016年11月11日
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
C言語 はじめに 2016年 吉田研究室.
プログラミング演習I 2003年4月30日(第3回) 木村巌.
11: 動的メモリ確保 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
12: コマンドライン引数 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページを開いておく こと
11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数
11: 動的メモリ確保 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページを開いておく こと
第5回 プログラミングⅡ 第5回
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
C プログラミング入門 基幹7 (水5) 14: 発展事項
情報処理Ⅱ 第7回 2004年11月16日(火).
11: 動的メモリ確保 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング 4 文字列.
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
11: 動的メモリ確保 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
全体の流れ 画像ファイルを開き,画像データをメモリ上にロード メモリ上にロードした画像データに処理を加える
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
プログラミング演習I 2003年6月11日(第9回) 木村巌.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
プログラミング言語論 第九回 理工学部 情報システム工学科 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
情報処理Ⅱ 第9回:2003年12月16日(火).
14: 発展事項 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
情報処理Ⅱ 小テスト 2005年2月1日(火).
情報処理Ⅱ 第8回:2003年12月9日(火).
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
12: コマンドライン引数 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング 2 静的変数.
Presentation transcript:

C プログラミング入門 総機1 (月1) 14: 発展事項 2014-07-13

これまでの講義で説明していない事項についていくつか簡単に紹介する 今日の内容 これまでの講義で説明していない事項についていくつか簡単に紹介する 静的変数 (static) const 変数 プリプロセッサ・ディレクティブ マクロ ファイルの読み込み 数学関数のエラーチェック 文法 関数ポインタ 標準入出力ファイル 可変長引数 異常終了 プログラミング技術 短絡評価 モジュールプログラミング 文字定数の型 外部リンケージ キャスト アサーション 変数の宣言位置 グローバル変数 2014-07-13 C プログラミング入門 総機1 (月1)

文法 2014-07-13 C プログラミング入門 総機1 (月1)

標準入出力 標準入力、標準出力はファイルの一種 標準エラー出力というのもある それぞれ stdin, stdout という FILE ポインタがグローバル変数で定義されている たとえば printf("Hello!"); は fprintf(stdout, "Hello!); と同じ 標準エラー出力というのもある fprintf(stderr, "Memory error\n"); 標準出力とは区別されていて、エラーを知らせる時に使う。標準出力がリダイレクトされてもエラーは画面に出る <stddef.h> で定義されているが、<stdio.h> などで読み込まれている 2014-07-13 C プログラミング入門 総機1 (月1)

main() から return で終了した場合を正常終了という 正常終了・異常終了 main() から return で終了した場合を正常終了という 標準ライブラリ関数 exit() を使っても同じ 終了時に自動的に呼ばれる関数を atexit() で登録することができる OS による検出などで強制的に終了することを異常終了という プログラムから意図的に行うには abort() を用いる シグナルをトラップして処理できる(詳細略) 2014-07-13 C プログラミング入門 総機1 (月1)

短絡評価 論理演算子の最初の式から全体の値が決まる場合、2つ目の式を評価しない たとえば、以下のような場合に意味を持つ (式1) && (式2) : (式1) が偽の場合、(式2) を評価しない (式1) || (式2) : (式1) が真の場合、(式2) を評価しない たとえば、以下のような場合に意味を持つ if(p != NULL && p[0] == 3) … もし p が null ポインタの場合、 p[0] は評価できないが、 短絡評価されるので問題ない 式全体として偽となる 式全体として真となる もちろん、 if(p != NULL) { if(p[0] == 3) ... } と書いてもよい 2014-07-13 C プログラミング入門 総機1 (月1)

文字定数 (文字リテラル) は char 型ではなく、 int 型である 文字定数の型 文字定数 (文字リテラル) は char 型ではなく、 int 型である 例: 'A' は ASCII コードでは int の 65 標準ライブラリ関数で文字を扱う関数では、文字を指定するのに int 型となっている 例: 指定した文字 ch を文字列 str から見つける char *strchr(const char *str, int ch); C++ では、文字リテラルは char 型である 2014-07-13 C プログラミング入門 総機1 (月1)

キャスト 数値を任意の型に強制的に変換する キャストの例 キャストはバグの温床なので多用しない 変換されるものに対して挙動が異なる 構文: (型)値 キャストの例 (int)4.5 4.5 を 4 に切り捨てる (int *)p ポインタの型を変える const 型を非 const 型に変更することもできる キャストはバグの温床なので多用しない () はいろいろなところで使われるので検索で見つけづらい 演算子の一種 const を使う意義がなくなるので、やるべきではない 2014-07-13 C プログラミング入門 総機1 (月1)

C89 まではローカル変数は必ずブロックの先頭で宣言する必要がある ローカル変数の宣言位置 C89 まではローカル変数は必ずブロックの先頭で宣言する必要がある C99 以降はどこでも可能になった GCC は標準で許容 C++ の文法を導入したもの 使用する直前で宣言するほうがコードが読みやすい { int i, j, k; // int sum = 0; ... 長いプログラム int sum = 0; for(... sum += s[i]; } ここで定義するよりは… ここでは sum は全く使われない ここで定義すれば、ここから始めて使われることがわかる 2014-07-13 C プログラミング入門 総機1 (月1)

グローバル変数 関数の外で宣言される変数 ソース全体の定数などに利用 宣言位置以降どこでも可視 初期化がない場合、 0 に初期化される #include <stdio.h> const int PI = 3.1415; int count; int func1(void) { ... } int main(void) const を付けて、定数として使う 実行開始時に 0 に初期化される デフォルトで外部リンケージを持つため、ほかのプログラムとの共有をしない場合は static を付ける。詳細略 2014-07-13 C プログラミング入門 総機1 (月1)

関数の変数宣言に static を付けるとグローバル変数と同様にプログラムの開始時から終了まで生存する変数となる 書かなくても 0 に初期化される 関数の変数宣言に static を付けるとグローバル変数と同様にプログラムの開始時から終了まで生存する変数となる スコープはその関数のみ 初期化を指定しない場合 0 に初期化される #include <stdio.h> int count(void) { static int n = 0; ++n; return n; } int main(void) printf("%d\n", count()); ... 呼び出すたびに 1 増える グローバル変数に対する static とは効果が異なる 2014-07-13 C プログラミング入門 総機1 (月1)

変数とポインタと動的メモリ確保の整理 再掲 2014-07-13 C プログラミング入門 総機1 (月1) 分類 生存期間 スコープ メモリ領域 初期化 自動変数 (ローカル変数) 定義位置からブロック終端まで スタック 初期化が指定されている場合のみ、ブロックに入るたびに初期化される 大域変数 (グローバル変数) プログラムの実行開始から終了まで 定義位置からプログラム終了まで 静的領域 プログラム開始時に1度だけ。初期化が指定されない場合、0 で初期化される 静的変数 (static 変数) 同上 動的メモリ 確保から解放まで ヒープ malloc() はされない calloc() は 0 を書きこむ 2014-07-13 C プログラミング入門 総機1 (月1)

# で始まるものは、プログラムのコンパイル前にプリプロセッサというソフトで処理される。これをディレクティブという プリプロセッサとディレクティブ # で始まるものは、プログラムのコンパイル前にプリプロセッサというソフトで処理される。これをディレクティブという #include によるヘッダファイルの読み込みや #define のマクロなどはこれの一種 #if, #ifdef, #ifndef, #endif, #define, #undef, #line などがある 詳細は、リファレンスサイトで調べてください。 2014-07-13 C プログラミング入門 総機1 (月1)

多くの場合マクロを使わず、グローバル変数を書くべき 主に定数を書く際に用いられる 通常のマクロと、関数型のマクロがある どちらも #define ディレクティブで定義する 例 #define MVAL 100 ソースコード中のすべての MVAL を、文字列 100 で置き換える 多くの場合マクロを使わず、グローバル変数を書くべき static const int MVAL = 100; 間に = を書かない 最後にセミコロンは付けない 関数の外で書く 値の型が必要 2014-07-13 C プログラミング入門 総機1 (月1)

標準ライブラリでは、定数の多くがマクロで定義されている 例 RAND_MAX 乱数の最大値 EXIT_SUCCESS, EXIT_FAILURE return の後に 0 や 1 を書く代わりに使う ERANGE 数学関数のエラーコード EOF ファイルの終端 2014-07-13 C プログラミング入門 総機1 (月1)

関数型マクロは、関数の様に引数を与えることができる 特に理由がない限り、普通の関数を使うべき 標準ライブラリ関数のいくつかはマクロである 例 #define xy2idx(x,y,w) ((x)+(y)*(w)) いつも決まった式を書く場合に便利 単純なソースコード上の文字列の置き換えになるので、解釈がおかしくならないように、引数それぞれと、式全体に括弧を付ける 2014-07-13 C プログラミング入門 総機1 (月1)

関数型マクロ 標準ライブラリの関数型マクロの例 getc(fp) fgetc(fp) と等価 assert(exp) exp が偽であれば異常終了する 2014-07-13 C プログラミング入門 総機1 (月1)

プログラミング技術 2014-07-13 C プログラミング入門 総機1 (月1)

関数の引数がポインタであり、それを通して値を変更しない場合は常に const を付ける(説明済み) コンパイラによる最適化(高速化)が期待できる 2014-07-13 C プログラミング入門 総機1 (月1)

アサーション(表明) (assertion) コメントで書くより効果的 ソースコード中で、常に成り立つ条件をコードで表す assert マクロを使う 条件を満たさない場合、異常終了する 常に条件が満たされるようにコードを書く #include <stdio.h> #include <assert.h> // n 要素の int 配列 a の総和 int sum(const int *a, int n) { int s = 0, i; assert(n > 0); assert(a != NULL); for(i = 0; i < n; ++i) s += a[i]; } return s; 条件を満たさない限り以降の処理が正しく行われないので、絶対に進ませない プログラムのバグがない ⇒ 全てのアサーションが真 2014-07-13 C プログラミング入門 総機1 (月1)

条件判断には計算時間がかかるため、リリース製品のような場合には無効化する アサーションの無効化 条件判断には計算時間がかかるため、リリース製品のような場合には無効化する NDEBUG マクロを定義すると、条件式が空行に置き代わる gcc では、コンパイル時に -DNDEBUG オプションを付ける 2014-07-13 C プログラミング入門 総機1 (月1)

バグのないプログラム⇒全てのアサーションが真 アサーションの考え方 バグのないプログラム⇒全てのアサーションが真 プログラマは、アサーションに違反しないように関数を呼び出すことを強制される(契約) アサーションは、多ければ多いほど良い 一度書いたアサーションは基本的に消さない 詳細は、以下のキーワードで調べてください 事前条件・事後条件・不変条件 ホーア論理 (Hoare logic) 契約プログラミング (Programming (Design) by Contract) 2014-07-13 C プログラミング入門 総機1 (月1)

コンパイルとリンク コンパイル (compile) リンク (link) ソースコードファイル オブジェクトファイル myprog1.c savePGM() drawLine() func1() main() myprog1.o 実行可能形式 (executable) myprog1 標準ライブラリ (libc.so) printf() malloc() ... それぞれを行うソフトウェアを、コンパイラ (compiler), リンカ (linker) という gcc は、これらを総合して実行するコンパイラドライバである 使用するコンパイラに付属するライブラリ 2014-07-13 C プログラミング入門 総機1 (月1)

いくつかのプログラムで共通の処理を、ソースコードから分離する モジュールプログラミング いくつかのプログラムで共通の処理を、ソースコードから分離する myprog1.c savePGM() drawLine() func1() main() myprog2.c savePGM() loadPGM() func2() main() myprog3.c savePGM() loadPGM() drawLine() main() 同じ関数が複数のプログラムに存在する pgm_module.c savePGM() loadPGM() drawLine() 共通の処理を抜き出す 2014-07-13 C プログラミング入門 総機1 (月1)

モジュールプログラミング コンパイル リンク pgm_module.c savePGM() loadPGM() drawLine() pmg_module.o モジュール myprog1.c func1() main() myprog1 myprog1.o モジュールに分けた関数は含んでいない 標準ライブラリ 2014-07-13 C プログラミング入門 総機1 (月1)

それぞれのソースをコンパイルして、オブジェクトファイルを生成 モジュール分けしたプログラムのビルド それぞれのソースをコンパイルして、オブジェクトファイルを生成 gcc -c -o pgm_module.o pgm_module.c –Wall –Wextra gcc -c -o myprog1.o myprog.c –Wall –Wextra リンク gcc -o myprog1 myprog.o pgm_module.o –Wall –Wextra 2014-07-13 C プログラミング入門 総機1 (月1)

外部リンケージ コンパイル リンク pgm_module.c savePGM() loadPGM() drawLine() リンクの対象となる公開された関数やグローバル変数は外部リンケージを持つという 関数やグローバル変数は普通は外部リンケージを持つ pmg_module.o 公開される関数 savePGM loadPGM drawLine myprog1.c static int func1(void); main() myprog1 myprog1.o 公開される関数 main 複数のオブジェクトファイルが同じ名前の関数や変数を公開している場合、リンクの結果は未定義である。したがって、最小限のものだけを公開する必要がある 他のモジュールから使われることのない関数, グローバル変数には static を付ける 標準ライブラリ 2014-07-13 C プログラミング入門 総機1 (月1)

モジュール分けするために以下のことをする モジュールの作成 モジュール分けするために以下のことをする モジュールで公開しない関数に static を付ける モジュールで公開しないグローバル変数に static を付ける モジュールのヘッダファイルとして、公開する関数のプロトタイプ、公開するグローバル変数の extern 宣言を書く ヘッダファイルにインクルードガードを書く モジュールで自分のヘッダをインクルードする 詳細は、書籍などを参照 2014-07-13 C プログラミング入門 総機1 (月1)