エキスパートCプログラミング
エキスパートCプログラミング―知られざるCの深層 (Ascii books)
- 作者: ピーターヴァン・デ・リンデン,Peter van der Linden,梅原系
- 出版社/メーカー: アスキー
- 発売日: 1996/03
- メディア: 単行本
- 購入: 17人 クリック: 404回
- この商品を含むブログ (78件) を見る
良い本だった。この本を学生時代に読んでいたら専門が変わっていたかもしれない。
- 型の違う場合の演算や比較
- 異なる型同士を演算あるいは比較する場合は、きちんとキャストすること。
- unsigned は気軽に使わない。
- const修飾 は readonlyの意味
- 勘違いしやすいCの文字列
- NUL: ASCII文字の一つビットパターンのゼロ
- NULL: 何も指さない特殊なポインタ
- 関数が見えすぎる(Cの欠点)
- 複数の意味を持つCのシンボル(Cの欠点)
-
- static
- 関数内では、「関数呼び出しの間にも、その値を保持せよ」
- 関数自体に対しては、「関数のスコープをファイル内に限定せよ」
- static
-
- extern
- 関数の場合、「グローバル関数である」(デフォルトなので冗長な宣言)
- 変数の場合、「どこかで定義してある」
- extern
-
- void
- 関数の戻り値の場合、「値は返さない」
- ポインタ定義の場合、任意の型へのポインタ
- 引数リスト内では、「引数無し」
- void
- 関数の引数は、右から左の順にスタックにプッシュされる?
- cdecl
- Cの宣言を解読して英語表現になおすプログラム
- 手元の環境には入っていない。
- 定義と宣言の違い
- 定義 (definition): 一回しか記述できない。オブジェクトの型を指定し、必要な領域を確保する。新規オブジェクトの作成に使う。
-
-
- 例: int my_array[100];
-
-
- 宣言 (declaration): 何度でも記述できる。オブジェクトの型を記述する。どこか(たとえば別ファイル)で定義されたオブジェクトを参照する。
-
-
- 例: extern int my_array[];
-
- 配列とポインタの違い
-
- ポインタ
- データのアドレスを格納
- データは間接参照される。最初にポインタの内容が取得され、それからその内容が参照される。
- ポインタに、添字[i]がついている場合には、先に"i"の内容も参照される。
- 普通は動的なデータ構造で使われる。
- 普通はmalloc(), free()などと一緒に使われる。
- 普通は名無しのデータを指す。
- ポインタ
-
- 配列
- データを格納
- データは直接参照される。a[i]では、iの内容を参照するだけでよい。
- 普通は特定要素数の同じ型のデータの格納に使われる。
- 自動的に確保、削除される。
- それ自身、名前の付いた変数である。
- 配列
- 文字列による初期化
-
- ポインタ
- ポインタの定義で確保されるのはポインタ自身の領域だけで、それが指すものの領域は確保されない。ただし、文字列によって初期化される場合は例外
- char *p = "breadfruit";
- ANSI Cではこのとき、文字列は書き込み禁止になる。(static変数としてdata segmentに値が入るから?)
- ポインタ
-
- 配列
- 同様に文字列による初期化が可能。ただし書き換え可。(stack segmentに値が入るから?)
- char a[] = "gooseberry";
- 配列
-
- 良くある文字列郡の定義方法
- ライブラリの中のシンボルを調べる
% foreach i (lib?*)
? echo $i
? nm $i |grep xdr_reference | grep -v UNDEF
? end
- コードとデータ
- コード: コンパイル時
- データ: 実行時
- Cではコードとデータをはっきり区別している。
- a.out
- 以下で、data, bss, textのサイズが確認できる。
- % size 実行ファイル
- dataセグメント: 初期化されたglobal dataあるいはstatic dataが格納される。
- bssセグメント: 未初期化globalデータに必要な"サイズ"が格納される。実行時にそのサイズが確保され、ゼロクリアされる。
- setjump, longjump
-
- 関数の外へジャンプできる。setjumpによってPCとstack位置をセーブする。longjumpがその値を復元する。(stackのunwindと呼ばれる処理)
- C++では、setjump,longjumpが、より一般的な例外機構であるcatch, throughに発展した。
- bus error, segmentation fault
- どちらも同じような意味だし、OSによって正確な意味も異なる
- bus error: ミスアライメントを主"原因"とするエラー
- segmentation fault: 異常なポインタ参照という"結果(症状)"によるエラー
- 1. 間違ったポインタ値
- 2. mallocエリア外へのアクセス
- 3. free()のミス
- クリスマス == ハロウィーン
- OCT 31 (8進数の31) == DEC 25 (10進数の25)
- C
- 10, 8, 16進数の定数は記述できるが、2進数の定数は記述できない。不便。
- 型の格上げ charはintになる
- 式の中では、charは自動的にintになる。sizeof 'A'の値は1でなく4(確認済)。
- 引数としてchar型を取るものはそのままcharです(当然)
- Unixで端末をrawモードで利用する簡単な方法
system("stty raw"); /* system("stty raw -echo"); */
c = getchar();
system("stty cooked"); /* system("stty cooked echo"); */
- 関数へのポインタ配列
- 宣言:
void (*state[MAX_STATES]);
-
- 呼び出し:
(*state[i])();
あるいは
state[i](); /* ANSI Cでは同じ意味!*/
- 値渡し, 参照渡し
- Cでは原則すべて値渡し
- ただし、配列と関数だけは例外で参照渡し。
- 配列を引数として関数に渡すコードにおいて、配列は、コンパイラによってポインタに変換される。結果として配列は参照渡しとなる。
- char文字列へのポインタの配列
-
- char *pea[5];
- a.out
-
- assembler outputの略
- ++i, i++の違い
-
-
- i++: xの位置を取得し、その値をレジスタに持ってきてから、メモリの中のxの値をインクリメントする。
-
- ライブラリとシステムコールの違い