なぜあなたは「配列へのポインタ」を学ぶ必要があるのか

かつて(20年くらい前)一緒に仕事をしていた人が、こう言ったことがあります。

はっきり言って、Cプログラマ過半数は、「配列へのポインタ」を理解していないと思う。

まあ「過半数」かどうかはわかりませんが、実際、それなりに長くCを使っている人でも、「配列へのポインタ」を理解していない人はいるように思います。以下、一例。

きくT(2/10 ビッグアップル) on Twitter: "んー、2次元配列を1次元にキャストして関数に渡すことはできるんだけど、1次元配列として受け取った関数側で2次元配列にキャストする方法はあるのか?"
f:id:kmaebashi:20171217185156p:plain

もちろん菊池誠先生は物理学者であり、Cは専門ではないでしょうから、このことをもって菊池先生のことをとやかく言う意図はありません。

それにしても、リプライ中にある以下の記述は、やはりCの初心者の方にとっては「わけがわからない」ものであるかと思います。

Int (*b)[5] = (int(*)[5])a;

int (*b)[5]」なんて、こんなマニアックな書き方使わないよ!

と思う人もいるかもしれません。でも、現に菊池先生が困ったように、これを使う機会は、確実にあるものです。

「配列へのポインタ」を使う典型的なケースは、「多次元配列を関数の引数として渡す時」です。たとえばオセロの盤面をintの2次元配列(int board[8][8];)で表現するとして、これを引数として受け取る関数のプロトタイプは、たとえば以下のようになります。

void func(int (*board)[8]);

いや、そんなマニアックな書き方しなくても、

void func(int board[8][8]);

とか

void func(int board[][8]);

とか書けばよいのでは? と思う人もいるかもしれません。しかし、こうして受け取った引数を別の変数にコピーしようとした場合や、malloc()で動的に多次元配列を確保したい場合は、「配列へのポインタ」を宣言することを避けることはできません。
たとえばオセロの盤面をmalloc()で確保するなら、以下のように書くことになります。

int (*board)[8] = malloc(sizeof(int) * 8 * 8);

で、わざわざこんなの書いたということはもちろん宣伝なのですが、「配列へのポインタ」はもちろん、Cの配列とポインタについて徹底解説した「C言語 ポインタ完全制覇」改訂版発売中ですよ!

ちなみに旧版の画像はこちら。この画像を見せると「あっ、見たことある!」という方も結構いらっしゃるので。
f:id:kmaebashi:20171217195236j:plain

C言語 ポインタ完全制覇 改訂版が発売されます!!

2001年の発売より、実に17年、第18刷を数えるロングセラーとなった「C言語 ポインタ完全制覇」の改訂版が発売されます。

f:id:kmaebashi:20171203200126j:plain

 

私の作成した紹介ページはこちら。

「C言語 ポインタ完全制覇(第2版)」書籍情報

技術評論社さんの紹介ページはこちら

新・標準プログラマーズライブラリ C言語 ポインタ完全制覇:書籍案内|技術評論社

Amazonでは現在予約注文が可能です。

https://www.amazon.co.jp/o/ASIN/477419381X/gihyojp-22

技術評論社さんでの電子書籍版(PDF)販売、およびKindle化の予定もあります。

 

「なんでいまさらCの本?」と思う人が多いかもしれません。私自身そう思わなくもないので当然です。しかし、現在でも、WebやTwitterで検索してみると、Cのポインタで苦労している人はまだまだたくさんいるようです。ていうか著者からすると、最近書いた「Webサーバを作りながら学ぶ 基礎からのWebアプリケーション開発入門」よりも、17年も前に書いた「C言語 ポインタ完全制覇」の方がTwitter検索するとよっぽどたくさんかかってくる、という、喜んでいいのか悲しむべきなのか、という状況がずっと続いていたりします。

旧版「C言語 ポインタ完全制覇」は、自分で言うのも何ですが、Cのポインタおよび宣言の構文について、当時としては画期的な説明をした本であったと思っています*1。最近でも時々、「Cの宣言は英語順で読むといいよ!」という記事がはてなブックマークに上がってきたりしますが、この「英語読み」を日本で最初に言い出したのは、おそらくこの本(の原型となったWebページ)です*2

 Cのポインタで悩んでいる人も、Cのポインタが「わかっているつもり」の人も、だまされたと思って上記書籍情報のページくらいは読んでみてください。

今回の改訂では、旧版と大きく構成を変えたわけではないですが、さすがに17年も経てば直すべきところも出てきます。以下のような点で加筆・修正を行っています。

  • C99の可変長引数(VLA)やC11のライブラリに言及
  • ASLRやDEPといった今時の機能にも言及
  • サンプルプログラムの動作環境の64bit化
  • 1章に、「メモリとアドレス」の項を追加。17年前にCプログラマを志す人ならある程度前提にできたかもしれませんが、今時はそうもいかないと思われるので。
  • 「補足」を目次に載せました(これはご要望が多かった!)。
  • その他、細かい修正。

何しろ旧版が323ページのところ、今回は367ページありますので、相応の書き足しを行ってます。旧版をお持ちの方も、ぜひどうぞ。 

*1:と言いつつ、実のところ文法通りの説明をしているだけなので、「なぜ私以外の人がもっと早くこういう本を書いてくれなかったんだろう」というのが正直な気持ちでもあります。

*2:たとえば「エキスパートCプログラミング」にも宣言を読むダイアグラムはありますが、いきなり日本語を組み立てているので末尾から文章を作るという妙なことになっています。どうして訳者注くらい入れてくれなかったんだろう……

車道を走ってきた自転車はどこで信号待ちすべきか

最近はクロスバイクとかロードバイクとか、あるいはママチャリでも、車道を走る自転車が増えている気がします。自転車は、車道を走った方が、歩行者を脅かさないというだけでなく自転車自身にとっても安全なので、これはよい傾向だとは思うのですが。
そうやって車道を走ってきた自転車は、赤信号の時、どこで信号待ちすべきでしょうか。
答から先に書けば、停止線で止まるべきです。当たり前です。

f:id:kmaebashi:20171127001241p:plain

ところが、実際に道路で見てみると、横断歩道を越えて、自転車横断帯の前まで行って待とうとする人が多い。非常に多い。

f:id:kmaebashi:20171127001559p:plain

これだと、青信号で横断歩道を渡っている歩行者の中を突っ切ることになります。これが正しいわけがありません。

ただ、気持ちとしては、わかる部分もあります。なにしろ交差点にはわざわざ自転車の絵をペイントした自転車横断帯があり、自転車はここを渡れと法律で定められている。ここを渡れというのなら、その手前で待つべきなのでは? と思うのも無理はありません。実際、歩道を走ってきたママチャリなら、自転車横断帯手前で待つのが正しいのでしょう。

しかし、車道を走るなら、停止線で止まるべきです。そうでないと上の図のように歩行者の中に突っ込むことになります。

名古屋の街を走っていて、自転車横断帯手前で待とうとして横断歩道に突っ込む自転車があまりに多いので書きました。彼らに悪意はないのだと思います。しかし、歩行者から見れば、「暴走自転車が歩道に突っ込んできた」と見えることでしょう。単なる知識不足から、歩行者と自転車乗りの間で無駄な衝突(物理的な衝突だけでなく、感情的なものも含めて)が起きるのは、双方にとって不幸かと思います。

で、信号が青になった時、どう走るべきか。常識的に考えればまっすぐ走ればよいはずですが、自転車横断帯がある場合そこを走ることが法律で定められて…… という話は、面倒なのでお茶を濁しておきます。いやほんと、自転車横断帯が歩道から生えているというのは、日本の、自転車に関する法律の矛盾の象徴だと思うことですよ。

プログラミング言語C(K&R)邦訳のバージョン違いについて

プログラミング言語C(通称K&R)の邦訳版と言えば、

  • ANSI C対応以前のもの。白い表紙。
  • 第2版。ANSI C規格準拠。薄緑の表紙。
  • 第2版訳改訂版。訳だけ改められた。白い表紙。

 の3種類だと思っていたのですが、第2版訳書改訂版に、私が持っているのとは異なる(古い)バージョンがあるらしい、ということをある方から聞きました。

私が持っている、訳改定前(薄緑表紙)の奥付:

1989年6月15日 初版1刷発行

1992年2月20日 初版101刷発行

 

私が持っている、訳改定版(白表紙)の奥付:

1989年6月15日 第2版1刷発行

1997年5月1日 第2版211刷発行

 

この奥付を見るだけでも、1989年6月15日に出たのは初版なのか第2版なのか不安になりますが……

情報をくださった方が持っているものは、訳書改訂版の「初版156刷 1994年3月10日付」だそうです。時期的には、訳改訂版でありかつ私の持っているもの(211刷)よりは前のもの、とういうことになりますね。

で、気になるのは、拙著「C言語 ポインタ完全制覇」にも引用した(p.以下の箇所の訳です。

原文:

When an array name is passed to a function, the function can at its convenience believe that it has been handles either an an array or a pointer, and manipulate it accordingly.

時系列で並べると、

訳改定前(薄緑表紙) 1992年2月20日 初版101刷:

配列名が関数に渡されるときに、関数ではそれが配列として渡されたのかポインタとして渡されたのかが適当に判断され、それに応じた取り扱いが行われる。

情報をいただいたもの。1994年3月10日 初版156刷 :

配列名が関数に渡されるときに,関数ではそれが配列として渡されたのかポインタとして渡されたのかを適当に判断して,それに応じた取り扱いをしてよい.

訳改訂版(白表紙) 1997年5月1日 第2版211刷 :

配列名が関数に渡されるときに,関数ではそれが配列として渡されたのかポインタとして渡されたのかを都合のよい方に判断して,それに応じて操作が行なわれる.

普通は、増刷の度に誤訳等を直していくのだと思うのですが、ここに関する限り、3番目の「第2版211刷」は、「初版156刷」より、訳改訂版以前の「初版101刷」に先祖返りしているように見えます。

 

ところで、K&Rの訳書改訂版が出る前に松井潔さんにより作られた誤訳の一覧があり、今でもvectorからダウンロードできます。訳書改訂版はかなりこれに沿った修正が行われています。

K&R 2nd. 邦訳書の正誤リストの詳細情報 : Vector ソフトを探す!

 この正誤リストにおいて、上記の箇所は、以下のようになっています(後続の1文を前橋にて削っています)。

訳書 ・・それが配列として渡されたのかポインタとして渡されたのかが適当に判断され、それに応じた取扱いが行われる。

正 ・・それが配列として渡されたのかポインタとして渡されたのかを適当に判断して、それに応じた取扱いをしてよい。

どうも、訳書改訂版作成時に、松井潔さんの正誤リストを元に修正し、それをまた後に戻したように見えます。

訳としては、私は英語が苦手なのでアレなんですが、

『主語は「the function」であり、canの後に、believeとmanipulateが並列で続いている』

と考えると、松井潔さんの訳でよいように見えます(can believeとmanipulateが並列なら、初期訳でよいのかな)。ただ、「それに応じた取り扱いをしてよい.」という言い方だと、日本語ではこの部分の主語が「プログラマ」であるようにも読めます。そして、元々この文章は原文からして意味不明なのですが(ポインタ完全制覇にも「まるで意味不明」と書きましたが)、この部分の主語を「プログラマ」だと解釈すれば、なんだか意味が通じるような気がします。プログラマは、ポインタとして渡された引数sについて、*(s+i)のように書くこともs[i]のように書くこともできるからです。情報をくださった方も、そう解釈できるのでは、と考えたそうです。

しかし原文では主語はやっぱり「the function」なので、だから戻したのかなあ、とも思えます。その場合、やっぱり「まるで意味不明」であると私には思えるのですが。

 

はてなブログを開設しました

はてなダイアリーは新規募集を停止したそうだしはてなブックマークのホットエントリーに上がってくる頻度も減ってきた気がするし、ということで、はてなブログを開設しました。
http://kmaebashi.hatenablog.com/
K.Maebashi's はてなブログ
今後は原則として新規記事はそちらに上げます。

よろしくお願いいたします。

自転車で名古屋から京都に行ったよ、という話

この前の夏休みに京都に行ってきました

名古屋近辺の自転車乗りにとって、京都というのは割と定番の行き先だと思います。

私も過去5回ほど行っています。他に行くところはないのか、と言われそうですが、150kmくらいで1日で走るのにはちょうどよいのと、新しいルートを調べるのがめんどうで、なんだか長期休暇のたびに京都に行ってしまいます。

1回目 2015年5月 一宮経由で行きだけ。帰りは輪行
2回目 2016年5月 一宮経由で往復。雨が降って稲沢でリタイア。
3回目 2016年8月 行きは一宮経由。帰りは養老経由。
4回目 2017年5月 養老経由で往復。
5回目 2017年8月 行きは養老経由。天気が持たず帰りは輪行

 コースは基本関ヶ原から21号に乗って琵琶湖に突き当たったら南下して近江大橋を渡り、あとは1号線に乗る、というものです。関ヶ原までのルートとして一宮経由と養老経由があり、一宮経由の方が平坦なので最初はそちらを使っていたのですが、養老経由で関ヶ原に行くというのは私が週末にちょくちょく走るコースであり、道を知っているので最近はそちらです。交差点のたびにスマホ見て地図を確認するのも面倒なので。

午前6:00過ぎぐらいに名古屋を出て、到着が午後6:00頃になったりするレベルのヘタレですが、同じように京都に行こうという人の参考になりましたら。

ルート全体:

f:id:kmaebashi:20170911012415p:plain

名古屋~関ヶ原

f:id:kmaebashi:20170911012743p:plain

起点は便宜上名古屋駅にしています。豊公橋で庄内川を越え、県道79号に乗ります。

出発! 時刻は06:35。

以下、ルートは2017/08/13に行ったときのものですが、写真はそれ以外の日に撮ったものも含まれます。

f:id:kmaebashi:20170813063520j:plain

途中、陸橋がありますが、軽車両進入禁止なので左の側道に入って踏切を渡ること。

f:id:kmaebashi:20170911014942j:plain

このファミマのある交差点(町方新田新西馬)で右折。

f:id:kmaebashi:20170903113952j:plain

藤ケ瀬のミニストップのある交差点で左折。ここのミニストップは、サイクルスタンドなんかもあったりして、なかなか自転車フレンドリーです。

f:id:kmaebashi:20170911013906p:plain

サイクルスタンド。やや低い。

f:id:kmaebashi:20170402141139j:plain

東海大橋で木曽川長良川を越える。

f:id:kmaebashi:20170813080210j:plain

福岡大橋で揖斐川も越える。

f:id:kmaebashi:20170911014128p:plain

f:id:kmaebashi:20170813081843j:plain

ここから、養老山脈を越えることになります。途中、コンビニ絶滅地帯で、自販機はあるものの財布には5000円札からしかなく、当然こんな山道の自販機がマナカとかに対応しているはずもなく、ということでようやくコンビニに辿り着いたの図。

f:id:kmaebashi:20170813085029j:plain

養老ランドの近くのカフェでモーニング。朝ごはんも食べてきているんですけどね。

f:id:kmaebashi:20170813092008j:plain

その後、広瀬橋南の交差点で川を渡って、関ヶ原西町のサークルKのある交差点で21号に乗ります。

f:id:kmaebashi:20170911013708p:plain

f:id:kmaebashi:20170813101829j:plain

2019/05/02追記:

このサークルKは、2019年4月末現在、更地になっています。

f:id:kmaebashi:20190427103845j:plain

関ヶ原~琵琶湖

f:id:kmaebashi:20170911013753p:plain

21号を走っているところ。こういう、コントラストの強い夏の風景ってぐっと来ませんか。

f:id:kmaebashi:20170813102614j:plain

21号線沿いのローソンで補給。補給といえばハンガーノックを恐れて甘いものを主体とすることが多いと思うのですが、この時期、塩分の補給もいるかな、とこんなものを。

f:id:kmaebashi:20170813105107j:plain

「西円寺」の交差点で21号を降ります。

f:id:kmaebashi:20170911014425p:plain

f:id:kmaebashi:20170430101206j:plain

その後、米原警察署の交差点で陸橋に乗ってJRをまたぎます。この陸橋、軽車両進入禁止ではないはずですが、2段階右折で乗ろうとすると信号が車両感応式で、車が来ないと渡れない…… ちょっと越えてから左折で乗るのが正しいのかしら。

f:id:kmaebashi:20170911014036p:plain

で、その後「喫茶エイト」とファミマがある交差点で左折。

そのファミマのトイレにて。なんだこれは。

f:id:kmaebashi:20170813113702j:plain

女子トイレはこう。

f:id:kmaebashi:20170813113712j:plain

その後1回左折して、「お食事処つるつる」へ。ほぼ毎回ここで昼ごはんを食べてます。

f:id:kmaebashi:20170911014157p:plain

f:id:kmaebashi:20170813120131j:plain

f:id:kmaebashi:20170430103050j:plain

天ぷらざるそば。

f:id:kmaebashi:20170813122428j:plain

このお店のすぐ裏が琵琶湖。

f:id:kmaebashi:20170813120056j:plain

昼飯食べて再出発。湖岸道路を南下します

f:id:kmaebashi:20170813124437j:plain

湖岸道路

f:id:kmaebashi:20170911014240p:plain

湖岸道路南下中。

f:id:kmaebashi:20170813135821j:plain

そのまま湖岸道路を走り続けてもよいのですが、一部道が曲がりくねっているので、田舎道を走ってショートカットします。名古屋からで計測すると109kmくらいのところにあるローソンの角で左折。

f:id:kmaebashi:20170911014347p:plain

f:id:kmaebashi:20170813144624j:plain

田舎道~近江大橋

f:id:kmaebashi:20170911014517p:plain

「堤」の交差点で右折、大水口神社を越えたところで左折、あとはGoogle mapsか何かで適当に見てみてください。

f:id:kmaebashi:20170813151750j:plain

途中、風車が見える。

f:id:kmaebashi:20170813151816j:plain

湖岸道路に合流した直後に見える、怪しげな宗教施設。調べてみたら、天聖真美会なる手かざし系の新興宗教の施設みたいですね…

f:id:kmaebashi:20170813154352j:plain

イオンモール草津に寄って銀だこのたこ焼きを食べます。本場大阪のたこ焼きは「外はカリッ」としてなくて、私は期待して行った大阪でたいそうがっかりしたことです。大阪の人からしたら邪道かもしれませんが、私は「外はカリッ」が好きですね。

f:id:kmaebashi:20170813161014j:plain

近江大橋には右折では乗れないので、ちょっとぐるぐる回る必要があります。

f:id:kmaebashi:20170911014723p:plain

近江大橋

f:id:kmaebashi:20170430154254j:plain

f:id:kmaebashi:20170813164911j:plain

1号線に乗る

この後、ちょっと住宅街のようなところを抜けて1号線に乗ります。Google地図に導かれてこのルートになったのですが、本当に生活道路なので、自転車とはいえ遠慮して走った方がよさそうです。

まず近江大橋を降りるところで車道に降りて、直進(?)して生活道路に入って、「カット&パーマ クレヨン」の角で左折して、片道交互通行の陸橋でJR東海道本線を越えます。

f:id:kmaebashi:20170911014553p:plain

1号線

これで1号線に乗ったら、あとは1本道です。

京都は盆地なので、坂はそこそこありますし、最後の上り坂の後にはトンネルがあったりもしますが。

f:id:kmaebashi:20170911014657p:plain

ラスト

f:id:kmaebashi:20170911014828p:plain

1号線は京都でいうところの五条通なので、適当に南下して七条通りに入ると京都タワーとか京都駅とかに着きます。

到着! (18:01)f:id:kmaebashi:20170813180148j:plain

5月に来たときは、06:19に出発して16:55着でした。結局すべては風向き次第でこれぐらいの時間差は出るようです。

というわけで、風呂で汗を流してからビール。

f:id:kmaebashi:20170813195657j:plain

名古屋から京都まで約150km、これぐらいなら誰でも1日で来られる距離だと思います。私など、初心者なので、足の筋肉痛とかより、お尻の痛さがボトルネックになります。

1日がかりで京都に行くとして、2日目を観光に当てて3日目に帰ってこようとすると、3日連続で晴れの日が必要になります(まあ、2日目は多少天気が悪くてもよいですが)。この夏休みはどうにも天候不順で、3日連続で晴れる日がなかったので、今回は輪行で帰りました。いやあ新幹線って早いですね(当たり前)。

下は自転車を輪行袋に詰めた図。逆さに立ててあり、ハンドルとサドルで接地しています。この状態を保つなら、エンド金具って要らないんじゃないかなあ(私は念のため付けていますけれども……)。

f:id:kmaebashi:20170814172744j:plain

 

 

「Webサーバを作りながら学ぶ 基礎からのWebアプリケーション開発入門」発売中です

ブログを開設したのでまずは自著の宣伝から。

Amazonで見ていただくとわかるように、私は6冊ほどプログラミング関連の書籍を書いていますが、

Amazon.co.jp: 前橋 和弥:作品一覧、著者略歴

現状での最新の本は(とはいえ1年以上前ですが……)、「Webサーバを作りながら学ぶ 基礎からのWebアプリケーション開発入門」です。

この本は、Webアプリケーション開発者向けの入門書です。

Webアプリケーション開発について、基礎の基礎から説明します。その手段として、本書では、Webサーバを作ります

Webサーバを作るといっても、PCを買ってきてLinuxApacheをインストールして、という意味ではありません。ApacheのようなWebサーバのプログラムを自作するということです。

基礎の基礎とは言ってもそれはいくらなんでも基礎に戻りすぎではないのか、そもそもWebサーバなんてそんな簡単に作れるものなのか、とツッコミを入れたくなる人がいるかもしれません。しかし、簡単なものであれば、Webサーバを作ることはさほど難しくはありません。本書で作成するWebサーバの初期バージョンは、Javaで140行程度のプログラムです。

また、Webサーバを作るというと、「OSを作る」とか「プログラミング言語を作る」といったような、ちょっとマニアックな行為に思えるかもしれません。しかし、本書で扱う程度のWebサーバを作る知識は、マニアックでもなんでもなく、普通のWebアプリケーション開発者が、当然の常識として知っていなければならないことです。

本書は、TCPソケットによる通信のサンプルプログラムから始まって、次に静的なHTMLを表示できるWebサーバを作り、最終的にはTomcatのへなちょこ版であるサーブレットコンテナ「Henacat」を作るという構成になっています。Henacatには、Cookie、セッション、ファイルアップロードといった機能も搭載します。

こういった機能は、なにも自分で作らなくても、いまどき何らかのフレームワーク等が面倒を見てくれるものです。そうやって生産性を上げるのはおおいに結構なのですが、フレームワークの使い方だけ知っていても、いざ何らかのトラブルが起きた時、手の打ちようがない、というのでは困ります。結局、Webアプリケーションを作ろうと思ったら、Webの基礎であるHTTPを知っている必要があるのです。

こう言っては何ですが、今時、日々Webアプリケーションを書いているプログラマでも、このあたりの基礎的な知識が欠けていて、コピペプログラミングを一歩越えようとすると行き詰まったり、バグが出ても原因究明ができなかったり、セキュリティーホールの説明とかが理解できなかったりする、という人は結構いるように思います。

このような趣旨の本ですので、本書の内容はかなり「古臭い」ものになっています。本書の内容の大半は、15年以上前の本に書いてあってもおかしくありません。というより、15年くらい前にこんな本があったら、私自身がもっと実感を持ってWebアプリケーションを理解できたのに、という思いが本書の出発点です。

プログラミング言語は普通にわかるけれど、Webアプリケーションを勉強しようとしたら、HTTPリクエストヘッダだのレスポンスヘッダだのContent-Typeだのよくわからない言葉がでてきて困っている、という(当時の私のような)人に、この本をおすすめします。

なお、本書は、以前より私のWebサイトで公開していた「本当の基礎からのWebアプリケーション入門――Webサーバを作ってみよう」の書籍版となります。

相当の修正、加筆がありますので、Webでタダで読めるなら本なんて買わなくていいやとか言わず、ぜひともお買い上げくださいませ。