tracks of engineering life

開発者人生の軌跡

読書メモ 『C言語 本格入門』

どんな本か

C言語の言語仕様について、基礎的な内容を網羅した本。サンプルコードが豊富。 実行環境のディストリビューションは限定してないが、Centosは5系での挙動を書いている。gccのバージョンは明記されてない。

読む目的は何か

  • 背景 Linux/Unixの本を読んでいたが、データ型や演算子の理解が曖昧なためCで書かれたサンプルコードをスラスラ読めなかったのが背景。 Cは実際にコードを書いたことがあまりないのでサンプルコードの写経を通して学習を進めたい。

  • 目的 以下の2点

    • 基本的な言語仕様の把握
    • 実際に手を動かすことでCの感覚を掴む

読んで大切だと思ったところのメモ

2,3,7,8,9章が自分の目的達成には必要だと思ったので、まずは2、3章を読んだ。 7、8、9章のメモは後日上げる予定。

2章

メモリとデータ型

  • メモリは有限な資源。メモリには0 or 1 の2ビットの値が格納され、32ビット/64ビットの単位でCPUはメモリを扱う。
  • ASCIIコードを利用した場合、半角英数字と記号は256通りが定義されている。つまり1文字は8ビットのメモリ領域を確保してやれば全通りを表現可能(28=256)
  • 32ビットCPUの場合、232=4,294,967,296 通りの0と1の組み合わせがある。つまり0から4,294,967,295までの整数を表すことが可能。
  • 整数を表すためには上記のように、32ビット分のメモリを確保することになる。int型で変数宣言すると32ビット分のメモリを確保し、char型で変数宣言すると8ビット分のメモリを確保することになる。
  • メモリは有限な資源なので、資源の使用効率を高めるために、C言語では変数宣言をする際は型宣言を行う。
  • 負の数は補数で表すが、コンパイラはそのままだとビット列が表すのが正の整数なの補数なのか判別できない。データ型を用いることでコンパイラに指示をする必要がある。

ソースコードのビルド

文字と文字列

  • 1文字を表すには8ビット必要であり、8ビットをメモリ上に確保するデータ型がchar。"hello world"のように複数の文字(文字列)を表示するには、charの配列を用いて表現する
  • Cにおいては配列とは、同じデータ型の変数を連続して並べたものというイメージ
  • 文字列を表現する際は、配列の最後の要素を\0という値にしなければならない。この値は文字列の終端を意味する。
  • char型の変数には数値を入れることで、ASCIIに対応した文字とのマッピングができる。
  • ASCIIの数字と文字列とのマッピング表を覚えて数値を入力するのは面倒なので、Cでは文字をシングルコーテーション''で囲うことで文字を数値へと変換している。'h'は104という数値へと変換される。
  • ダブルコーテーション""で文字を囲うことで、char型の配列として扱えるので通常はこちらを使う。
  • ただしダブルコーテーションで文字を囲うと、文字列定数として扱われる。
  • 一度宣言してしまった配列に値を代入したいときは、それぞれの要素を一つずつ指定しなければならない。配列の初期化を行えば要素を指定せずとも文字列を代入できる
  • Cでは関数においては、charやintなど普通の変数については、そのまま変数に格納した値をやり取りする。
  • 一方で配列や文字列のような大きな情報については、情報が格納されているメモリ領域の先頭アドレスだけでやりとりを行う。

記憶クラス

  • 関数の中で宣言した配列は、スタック上に保管される。関数の処理を終了した時点で、そのスタック上の空間は他の処理に使われてしまい内容が破壊される。
  • 破壊されないようにするには、スタック以外の領域に変数(メモリ領域)を確保する必要がある
  • 関数内の変数宣言時に先頭にstaticをつけることで、静的変数として変数をスタックとは別の領域に確保できる。
  • 静的変数はあくまでローカル変数であり、グローバル変数ではない。関数の外で宣言するのがグローバル変数
  • extern指定子を使うことで、別ファイルに宣言してある変数や関数を利用できるようになる。
  • "hello world" といった文字列定数は、const付きの変数として扱われる

3章 演算と演算子

  • sizeofは演算子
  • ビット演算は1ビットごとを対象にして演算を行うため、繰り上がりが発生しない
  • 繰り上がりはないが、桁だけをずらすビット演算もある
  • ビット演算を用いることで論理積の演算ができる。IPアドレス(192.168.0.1)とサブネットマスク(255.255.255.0)の論理積を求めると、ネットワークアドレス(192.168.0.0)が算出される。
  • 論理積論理和排他的論理和、シフト演算はビットでの演算となる。

所感

  • 文字列定数は罠すぎる。7、8、9章(文字列と配列、ポインタ、文字列操作)を読んで理解を深めたい
  • 論理積の記述はLinuxの本を読んでピンとこなかった部分だったが、本書のIPアドレスを例にした解説が分かりやすく理解が進んだ。
  • ウォーミングアップは済んだので、本丸の7、8、9章をこのまま攻略して難所を理解したい。