わさっきhb

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

愛読書(今年から教科書)にも誤記あり

C言語によるプログラミング―スーパーリファレンス編』は,Cプログラミングの講義を担当することが決まってから購入し,内容で気になったらいつも参照しています.
今年度から,この本を学科授業の教科書として,1年後期,2年前期のCプログラミング授業だけでなく,Cで何かを書くときに参照する本として,使っていく予定です.
なのですが,いくつか誤記があり,Amazonで最近購入した第1版第4刷(平成16年3月20日)でもそのままなので,ここで記載しておきます.授業を受ける学生のみなさんへ: 購入したら,鉛筆で加筆訂正しておいてください.

仮引数の不完全型配列変数

ちなみに不完全型のオブジェクトに対してsizeof演算子は適用できませんので,次のプログラムはエラーとなります.

double SumUp_1( double x[] )
{
  int k;
  int n=sizeof x/sizeof x[0];
  double s=0.0;

  for( k = 0; k<n; k++ ) s += x[k];
  return s;
}

(9.4.1 不完全型の配列, p.68)

「sizeof x」のところに,「xは不完全型なのでsizeof演算子は適用できないので,エラーとなる」と添え書きもあります.
この記述は丸ごと間違いです.すでに仮引数の配列変数は,ポインタなのか配列なのか - わさっきで述べ,私自身も勘違いがありましたが,関数の仮引数に書かれる配列型は,要素数を指定しても,「x[]」のように不完全型で指定していても,ポインタ変数になります.したがってコンパイル時点で,sizeof xを求めることができ,コンパイルエラーにはなりません.
ただし,文法的に問題ないことgrammatical correctnessと,プログラマの期待通り動作することとは別です.「sizeof x/sizeof x[0]」で,xの指す配列の要素数を求めることはできません.対策は,関数から見た配列のサイズは? - わさっきに挙げています.

演算子「~」

演算子一覧(11.2節,p.155),および単項演算子(11.3.2節,p.158)の中に,全ビット反転の単項演算子「~」が記載されていません*1

strncpy

strncpy() (14.18節,p.520)の注意の中に,「コピー先文字列にはナル文字が付加されます」と書かれていますが,これは間違いです*2.正しくは「fmの文字列長がn以上の場合、コピー先文字列にはナル文字は付加されません。」です.http://www.linux.or.jp/JM/html/LDP_man-pages/man3/strcpy.3.htmlにあるとおりです*3
関連して,

  • 細かいことですが,すぐ上の「(n+1)バイト文字列を格納するのに」は,「nバイト文字列を格納するのに」です.
  • strncat() (14.16節,p.518)の注意では明記されていませんが,「str2の文字列長がnバイト以上の場合、str1の示す文字列には、str2の文字列の先頭nバイトを付加し、さらにナル文字も付加します。」を書いておくほうがいいでしょう(参考: http://www.linux.or.jp/JM/html/LDP_man-pages/man3/strncat.3.html).

そういえばstrncpyは,2年後期の情報ネットワーク演習の中で苦渋をなめました.演習室のLinux環境では問題なく動き,TAが自分のCygwin環境で確認すると不具合となった原因が,このナル文字が付加されていなかったことだったのです.

*1:JIS X 3010:2003 6.5.3.3は,整数拡張や符号なし整数型にも考慮して,難解な記述になっています.「全ビット反転」は「1の補数」と等価,と言いたいところですが,符号なし整数に「1の補数」はそぐわないですね.

*2:JIS X 3010:2003 7.21.2.4 および脚注(259).

*3:演習室Linux環境で,「jman strncpy」を実行してみるのもいいでしょう.