トップページへ戻る プログラミングの禁じ手Web版 C言語編 - 直接コーディングに関しないパターン

/Top/今週のソースコード/プログラミングの禁じ手Web版 C言語編/
[←前] [次→]  [C言語版一覧] [C++版一覧]


一覧


直接コーディングに関しないパターン


warningを無視する

深刻度:★★★(重度)

[症状]

わけのわからないバグで悩むことになります。また,移植性や安定性に欠けるプログラムになります。

[原因]

プログラマの不勉強,怠慢が原因です。C言語のコンパイラのwarningは,ほかの言語のそれではerrorレベルになるものがあることを知らないために軽視しているものと思われます。

[対策/予防]

warningは問題のある部分をコンパイラがチェックした結果なので軽視するべきではないということを知らなくてはいけません。

[例外]

warningで報告されている内容が無視できるものであることを確認できるならかまわない場合もあります。ただし,そのことはプログラムのどこかに注意書きやコメントとして明記しておく必要があります。

[備考]

C言語以外のプログラム言語をやっていた人が,たまにつまづくのが,警告(warning)の扱いです。コンパイラがエラーと警告の両方のメッセージを出したとき,エラーに関してはきちんと修正するのに,警告については無視したり,原因をよく調べないで警告が出ないように適当にゴマカシをして,なんとか通してしまおうとする人を見かけます。しかし,そんな努力(?)も空しく,できあがったプログラムは,まともに動いてくれません。いったい,どうしたことでしょう?

C言語のwarningは本当に要注意で,もし設定で警告レベルを上げられるなら上げておき,ひとつひとつのwarningの原因を把握し,できるかぎり潰すほうが望ましいのです。なかには,わざわざ警告レベルを下げたり,設定を変えたり,警告レベルを下げるpragmaに詳しいというプログラマもいますが,それは技術力があるのではなく,ゴマカシ力,横車力があるとでも呼んだほうがよいでしょう。



stdio.hと同じディレクトリにプライベートヘッダを置く

深刻度:★(軽度)

[症状]

具体的な症状としては現れてきません。

[原因]

プログラマの怠慢も考えられますが,処理系標準のヘッダとプライベートヘッダの扱い方を知らないという不勉強がおもな原因です。

[対策/予防]

開発手順の常識を学んでもらうしかないのですが,身近によいお手本がない限り,解決は難しいと思います。

[例外]

なし。

[備考]

プログラムソースの置き方ひとつをとってもプログラマの性格や実力が現れます。筆者が見たなかで,もっともあきれてしまったのはstdio.hなどコンパイラの標準ヘッダのあるディレクトリに自分の作ったヘッダファイルを置いている例でした。こうなると,なんのためにディレクトリがあるのかわかっていないと思われます。実際の話,いい加減な仕事をする人たちでしたし,仕事もトロくさくて不得意で,バグを作り込むことだけが得意なようでした。



構造体のパッキングを無視する

深刻度:★★(中程度)

[症状]

移植性のないプログラムになります。

[原因]

プログラマの不勉強や怠慢が原因です。

[対策/予防]

自分が使用している以外のプラットホームについても勉強してください。

[例外]

特定のアーキテクチャや環境と心中するつもりなら許されるんでしょうかね。もちろん以降の禁じ手パターンでの例外も同様ですが筆者からの皮肉です。



エンディアンの存在を無視する

深刻度:★★(中程度)

[症状]

移植性のないプログラムになります。

[原因]

プログラマの不勉強や怠慢が原因です。

[対策/予防]

自分が使用している以外のプラットホームについても勉強してください。

[例外]

特定のアーキテクチャや環境と心中するつもりなら許されます(皮肉)。



ポインタをlong型変数で保持できると決めつける

深刻度:★★(中程度)

[症状]

移植性のないプログラムになります。

[原因]

プログラマの不勉強や怠慢が原因です。

[対策/予防]

自分が使用している以外のプラットホームについても勉強してください。

[例外]

特定のアーキテクチャや環境と心中するつもりなら許されます(皮肉)。

[備考]

これは,驚いたことに某技術雑誌の記事に堂々と書かれていた嘘です。すでに書いた本人は,その雑誌から消えているようですが,パソコン通信などでも「この人の本は買ってはいけない」と書かれるような人でした。

ポインタをlong型変数で保持できると決めつけていた件については,どうやらコンパイラが吐いたコードを逆アセンブルして,そこから「規格」を推理しているようでした[注4]。ところが,現実にはインテル32ビットプロテクトモード用のコンパイラで,long型が32ビットなのに対して,ポインタが48ビットとして実装されているものが実在するのです。では,この処理系が規格外の実装をしているのかというとそうではありません。C言語の規格には「ポインタはlong型変数で保持できる」という決まりはなく,ポインタを何ビットで実装するかは実装者にまかされるのです。

ここであげた「構造体のパッキングを無視する」「エンディアンの存在を無視する」「ポインタをlong型変数で保持できると決めつける」という禁じ手パターンはいずれも実装者に任された「処理系依存の仕様」を勝手に「C言語の規格」だと勘違いしていることに起因します。ここで,なぜこのような勘違いが起こるのか,そのプロセスを検証してみましょう。

C言語は「移植性が高い」といわれていますが,実際にC言語の規格として規定されているのは文法的な最低のガイドラインにすぎません。特定のプラットホームで動作するようにコンパイラを実装しようとすると,厳密に考えないといけないような部分が案外あいまいだったり,実装者まかせになっていることに気付きます。

たとえば自動変数を実装するのは「ひとつの関数のなかで保証され,関数から外に出たら無効になる」という性質を守るだけでOKです。そのため,自動変数をスタック領域に割り付けないで関数のなかでmallocで確保し,関数から出るときにfreeで解放するという実装にしても規格には違反しません。しかし,現実にはスタックが使用できる環境でこういう実装をするのはあまりにも馬鹿げているし,効率も悪いので,多くの処理系で「自動変数をスタック領域に割り付ける」という実装が選択されることになります。ところが,この事情を知らないで実際の処理系の動作から規格を推理しようとすると,自分の周りにある処理系だけを調べて「C言語では自動変数はスタック領域に割り付ける規格である」という嘘の結論に達してしまうわけです。

プログラムをする人が注意しないといけないのは,少数のプラットホーム,少数の環境だけしか知らないのに,自分はすべてを知ったと傲慢な考えに陥ることです。筆者が実際に会って,「この人は勘違いしているな」と感じる人は,たいていひとつのプラットホームしか知らない「井のなかの蛙」パターンでした。マイコンや組み込み機械のことしか知らない癖に大型コンピュータや汎用機のプログラマを馬鹿にする人,ワークステーションが最高で,それ以外はどうしようもないと断じている人など実装と規格を混同しそうなプログラマはどこにでもいます。

[注4]C言語の参考書でたまに見られる落とし穴で,著者に「技術力」がありすぎて,コードを逆アセンブルし,そこから無理やり「規格」を類推している場合があります。しかし本来,「規格」は規格書を分析して判断すべきものです。だいいちコンパイラが吐くコードは,コンパイラの実装者が決定した「実装」にもとづいたもので,厳密に規格に準拠しているという保証はありません(当然バグが含まれていることもある)。C言語に限らず,この手の「規格と実装の混同」現象はどこにでも見られる落とし穴です(これは筆者にも,そういう傾向があるので,おおいに注意しないといけない。いわば自戒の意味を込めて書いている)。



巨大な領域を静的に確保する

深刻度:★★(中程度)

[症状]

移植性のないプログラムになります。また,極端にパフォーマンスが悪くなる場合があります。

[原因]

プログラマの不勉強や怠慢が原因です。

[対策/予防]

自分の作業環境以外のプラットホームについても勉強してください。めぐまれていない環境があることを忘れないようにすることがたいせつです。

[例外]

特定のアーキテクチャや環境と心中するつもりなら許されます(皮肉)。

[備考]

ワークステーションや大型機などの「恵まれた」資源が常識だと思い込んでいるプログラマが陥りやすい罠で,巨大な配列を作ったため,それが資源の少ないマイコンやパソコンの上でハングアップしたり,あるいは動作はするものの極端に遅かったり不安定なプログラムになるというものです。場合によってはプログラムを実行する以前にサイズが大きすぎるというエラーメッセージが出てコンパイル,リンクが通らないこともあります。

ただし,巨大といっても,最近ではどのくらいを巨大と呼んでいいのかわからなくなっています。筆者のような「古い」プログラマは,MS-DOSの640Kの壁,1セグメント64Kの壁の記憶が生なましいので,自動変数で1メガの配列を作って動かないとわめいているプログラマを「アホか」と冷ややかなまなざしで見る傾向にあります。実際,ファミコンのCPUが6502で,スタック領域が256バイトだった時代には64Kバイトは巨大と感じましたが,2000年の現代では1ギガバイトのハードディスクを「小さい」と感じるのも事実です。それゆえ,巨大とはそれぞれに与えられた制約や課題を元に冷静に判断してもらうしかありません。


△[全パターン一覧へ戻る] △[一覧へ戻る] ▲[Topへ戻る]

C MAGAZINE編集部