DATE : 2006/10/07 (Sat)
「クライマーズ・ハイ」(NHK 総合、原作:横山秀夫)を見ました(原作の小説も読了しました)。
「日本航空123便墜落事故」をベースに、揺れ動く地元新聞社周辺の1週間を描いたドラマ、小説です。
この作品の中では、組織と個人との利害関係の対立が常に描かれていきます。個人の思いが組織の論理で歪められ、逆に行き過ぎた思いが組織の論理を破綻させるというように、組織と個人の間を主人公を含めた登場人物があちこちに揺れ動いていきます。
「書くことは怖い」と主人公はドラマの中で言います。また、「感情と言葉は違うものだ」とも言います。
言葉は、他人に自分の意図や感情を伝える道具と言えます。しかし、自分の言葉を意図した通りに相手が解釈してくれるとは限りません。というのも、言葉を解釈するのは相手であり、相手はそこから自分の意図を推測するしかないからです。それが面を向け合った会話であれば表情や身振り手振りといった情報が相手の推測を手助けしてくれます。しかし、文字面だけでは、解釈は完全に相手任せになります。
例えば、「バカ」という言葉がメールで送られてきたとします。例え送り主が一種のほめ言葉としてや冗談として送ったとしても、受け取った方は罵られたと感じるかもしれません。
「クライマーズ・ハイ」というのは、「登山中に興奮状態が極限にまで達し、 恐怖感が麻痺すること」を言うそうです。そして、もし頂上に着く前に「クライマーズ・ハイ」が解けてしまうと、それまでの恐怖感が一気に噴き出して一歩も動けなくなるそうです。
文章を書いていると、得てして「ハイ」になることがあります。しかし、「ハイ」のまま文章をアップロードしてしまうと、後で大変なことになる場合もあります。例えば、個人情報を過剰に盛り込みすぎた記事をアップロードするとどうなるでしょうか。
(;^ω^)そうでなくとも、間違いだらけの記事をアップロードしてしまうこともあります。すると、後でとても恥ずかしい思いをします
山登りは頂上に登るだけでなく、下りがあります。しかし、文章を書いていると、頂上に登りきった時がゴールと思いがちです。
(;^ω^)例え簡単な記事でも下り(推敲)を意識したほうが良さそうです
(;^ω^)もしくは、登っている途中で意図的に「ハイ」な状態を解くか、です。しかし、これはなかなか至難の業です
(;^ω^)……と感じた TV ドラマと小説でした(実際には、もっといろいろな要素が絡み合っています)
DATE : 2006/10/06 (Fri)
C 言語では、ヌルポインタは次のように定義されています。
#define NULL ((void *) 0)
それに対し、C++ では次のように定義されています。
#define NULL 0
C 言語では void 型のポインタだった NULL が、C++ ではただの整数値になっています(コンパイラによって、int 型や long 型に定義されています)。
これは、C++ の型チェックが C 言語と比べて厳しくなったためです。C 言語式では void 型のポインタに型を決定していますが、C++ 式では型を決定付けていません。つまり、C++式の場合は、NULL 値がそのポインタにあった型に自動的に変換されることになります。
(;^ω^)ちなみに、マシンによってはヌルポインタが0番地を指さないものもあります。ただし C や C++ のコンパイラは、ポインタ変数を0で初期化していたり代入、比較しようとしていると、0を自動的にそのマシンに応じたヌルポインタの値に変換してくれます。
しかし、C++ 式では特定の場合に問題が発生します。
次のような関数を考えてみます。
void function(Object* obj) { ... } void function(int i) { ... }
そこで、次のような呼び出しを考えます。
function(NULL);
Object* を引数にとる関数か、int を引数に取る関数のどちらが呼ばれるかは、コンパイラに依存します。そのため、上のようにポインタと int 型とでオーバーロードするのは推奨されていません。
なお、上の関数を正しく呼び出すには、それぞれの引数の型に NULL をキャストします。
このように、C++ の NULL は特別な値ではなくただの整数値であるために、誤解を招きやすい形になっています。そのため、「NULL」を使わずに「0」とそのまま書くことが推奨されています。
(;^ω^)特に、C 言語 → C++ と勉強してくると勘違いしやすいところですね
ちなみに、将来の C++ の仕様では、ヌルポインタを表す予約語が定義されるそうです。
参考文献
(;^ω^)勉強日記の最後にまとめて書こうかと思ったのですが、かなり多くなりそうなので、それぞれのページに付けていこうと思います。
- プログラミングの禁じ手Web版 C++編 - 理念の誤解に関するパターン「C++はC言語の完全な上位互換性があると思い込む」
- C++言語解説 テキストNo.1-5-3 ~ポインタのダークサイド~
- Bjarne Stroustrup's C++ Style and Technique FAQ "Should I use NULL or 0?"
- よりよいC : 空ポインタ定数
- C 言語 FAQ 日本語版「5章 ヌルポインター」
- C++ Topic 「NULLより 0 の方がいい」
- ひげぽん OSとか作っちゃうかMona- [Effective C++][C++] ポインタと数値型とにオーバーロードするのは避けよう 25項
- NULL について
DATE : 2006/10/04 (Wed)
C++ にあって C 言語(C99よりも前のもの)にはないものとして、bool 型の存在が挙げられます。
bool 型とは、真偽値を表す型で、true と false の2値からなります。
(;^ω^)Java で言う boolean 型ですね
ただし、true と false はそれぞれ int 型に変換できます。具体的には、true が 1、false が0となります。
(;^ω^)Java では boolean 型は他の型に変換できませんが、C 言語の条件分岐は 0 が偽、0以外が真という扱いでしたから、その名残なのでしょう
例えば、次のように bool 値を表示するとします。
cout << true << endl; cout << false << endl;
すると、次のような結果になります。
1 0
このように bool 値そのものが int 値と同じように扱えるため、条件分岐の際には bool 値をそのまま使います。
bool isValid = check(); if (isValid) { // OK } else { // ERROR }
(;^ω^)ここらへんは、Java と同じような書き方になりますね
ちなみに、false は int 値の 0 と等しいため、NULL ポインタも false と等しくなります。
すると、NULL チェックは次のように書けます。
// 処理に成功した場合は生成した Object を、 // 処理に失敗した場合は NULL ポインタを返す関数 Object* createObject() { ... } int main() { Object* object = createObject(); // NULL チェック if (object) { // OK } else { // ERROR } }
0(NULL ポインタ)以外は(当然のことながら)非0なので、NULL ポインタでなければ上の if 文は成立します。
DATE : 2006/10/03 (Tue)
夜中、私の部屋の中は数本の蛍光灯で照らされています。
しかし、気が付かないうちに1本切れ、さらにもう1本と、蛍光灯の寿命が次々と尽きていきました。
そして今日の夜中、部屋の蛍光灯をつけてみると……
(;゚Д゚)部屋全体が点滅しているではありませんか
(;´Д`)最後の光を放っていた蛍光灯にとうとう寿命が来てしまいました
(;^ω^)なんとか予備の蛍光灯があったので交換しましたが、残像が目に焼きつくほど目に悪そうな状態でした
DATE : 2006/10/02 (Mon)
(;´Д`)そういえば、配列については全然触れていませんでした。そこで、この記事で簡単に触れたいと思います。
Java では、配列は次のように生成します。
int[] numbers = new int[3];
配列の要素数は、変数や定数で指定することもできます。
int[] numbers = new int[count];
int[] numbers = new int[COUNT];
C++ の場合は、これまでにオブジェクトを生成してきた場合と同様に、静的に宣言する方法と動的に生成する方法があります。
静的に宣言するには、次のようになります。
int numbers[3];
ただし、静的に宣言する場合、変数を要素数の指定に使うことはできません。静的な宣言の場合に使えるのは、整数値と定数のみです。
ちなみに、定数は次のように宣言します。
static const int COUNT = 3;
(;^ω^)Java の static final と似ていますね。
初期化も同時に行うには、次の通りです。
int numbers[3] = {1, 2, 3};
また、動的に生成するには、次のようにします。
int* numbers = new int[3];
この場合は、変数も要素数の指定に使えます。
初期化も同時に行うには、次の通りです。
int* numbers = new int(1, 2, 3);
なお、動的に生成した配列を解放するには、次のようにします。
delete [] numbers;
delete の後に「[]」を付けるところがミソです。「[]」を付けない場合、配列全体のメモリは解放されますが、numbers が直接指すオブジェクト(numbers[0])のデストラクタしか呼ばれません。すると、numbers[1]~[9]のデストラクタが呼ばれず、メモリリークを起こす可能性があります。
ちなみに、Java の配列と C++ と配列には大きな違いが2つあります。
- C++ の配列は要素数を保持しない。
- C++ の配列の要素は未初期化状態。
Java では、次のようにすることで配列の要素数を取得できました。
numbers.length
しかし、C++ の配列そのものから要素数を取得する方法はありません。
また、Java の配列は、生成すると全要素が自動的に初期化されます。例えば、int 型の配列の場合は、生成時に全要素が0に初期化されます。
しかし、C++ の配列は、静的な宣言、動的な生成ともに要素が初期化されていません。そのため、配列を初期化する処理が必要になります。
(;^ω^)ここらへんは実に C らしいですね
ちなみに、C++ の標準ライブラリには vector というクラスがあります。このクラスは、要素数が動的に変わる配列を実現したもので、要素数を取得できたり、要素を追加・削除と言った処理も簡単に行えるようになります。
(;^ω^)そういえば、Java にも java.util.Vector というクラスがありました。