わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

1990年代のCプログラミング

訳書として1996年4月に初版発行,そして手にしているのは2006年11月の第1版第14刷なのですが,この本は,Cのプログラミングをもう少し深く理解したい学生におすすめしたいです.
MS-DOSの話もわずかにありますが,それは昔話と割り切ればいいだけのことで,全体として,処理系に依存しない,Cの勘所が広く深く書かれています.
「chapter 4 なんてこったい! 配列とポインタは別物だったのか!」の章を読むと,配列とポインタの違いをどのように分かりやすく伝えるかhow to explain clearlyは,このころからの課題だったのだなあと感じます.
ただし,それぞれの主張を批判的に読むことが要求されます.誤記は見当たりませんでしたが,現在となっては不適切なことを勧めているものもあります.
以下ばらばらと,気になった箇所を引用します.

構造体を定義するたびにtypedefを付けるような真似はやめること.
それをしたところで,"struct" とタイプする手間が省けるだけだ.その反面で,データの構造が見えなくなってしまう.
(typedefワンポイント講座, p.102)

…いや,データの構造を隠すという目的では,typedefつきの構造体定義が推奨されるべきなんですが.

C++だけにある制限:

  • typedef名と構造体のタグ名は,C++では衝突してはならない.Cでは衝突してもいい(それぞれが独立した名前空間を持っている).

(CからC++への移行, p.307)

…おっと,これは初めて知りました.教えているのはCのみとはいえ,注釈をつけるべきですね.

C++では,const変数を使って配列サイズを指定できる.

const int size=128;
char a[size];

上のコードはCではエラーになるが,C++では問題ない.
(C++がCより進歩した点, p.306)

…あ,これは去年苦労しました.「CとC++の違い」として,覚えておけばいいのですね.

CとC++では意味が違うもの

  • 文字定数は,C++ではchar型だが,Cではint型だ.つまりsizeof('a')の値はC++では1に,Cではもっと大きな値になる.

(CからC++への移行, p.307)

…う〜ん,このルールの違いは要注意.まあ文字配列に文字型の値を代入したり,逆に取り出したりするときには,1バイトのほうが合理的なのですが.

my_function( int my_array [10][20] );

これは最も単純であるが,関数が扱える配列が正確に10×20のint配列に限られるため,最も使いにくくもある.パラメータとして可能な限りさまざまな多次元配列,できれば任意サイズの配列を扱えるようにしたいのだ.配列の最高位の次元のサイズは,指定しなくてもいいことを思い出して欲しい.関数が知っておく必要があるのは,他の次元のサイズと,配列のベースアドレスだけだ.それによって,行をまるごと「飛び越えて」次の行にアクセスできるのだ.
(p.267)

…いろいろおかしい.まず「正確に10×20のint配列に限られる」というのは間違いで,このように書いても,関数内のmy_arrayは,ポインタ変数になります*1
それ以降の要望については,関数がとる引数の「型」(コンパイル時に決まり,不適合な型を実引数に与えると,コンパイル時に警告またはエラーとなる)と「値」(実行時に決まる値で,ここではポインタ値=アドレスになる)とを区別すれば,何ができて何は理不尽な要求なのかが分かるものですが.
それと,上の関数プロトタイプ,そして本文で直後(引用しませんが)の等価な宣言について,関数の戻り値の型を書いていないのもおかしいです.

*1:関数プロトタイプ内のmy_arrayは,配列変数と見なしても,仕様上,問題ありません.とはいえ宣言なので,変数の実体は作られませんが.