よくわかるかどうかわからない現代魔法(その 3)
今回は「二つの『ルーン文字』の効力を入れ替える『呪文』」を作ってみたいと思う。
第一の失敗
まずは「呪文」を作る前に、どうすれば「二つの『ルーン文字』の効力を入れ替える」ことができるか考えてみよう。素朴に書くとしたらこうだろうか。
#include <stdio.h> int main() { int a = 3, b = 2; printf("a = %d, b = %d\n", a, b); a = b; b = a; printf("a = %d, b = %d\n", a, b); return 0; }
int a = 3, b = 2;
のところは丁寧に書くと
int a; int b; a = 3; b = 2;
だが省略して
int a = 3; int b = 2;
さらに省略するとさっきの書き方になる。それはそれとして、パッと見はこれで良さそうである。b
を a
にして、a
を b
にするんだから。ところが…。
a = 3, b = 2
a = 2, b = 2
おや ? a
の「効果」はどこへ消えた ?
失敗の原因は
a = b;
の部分である。この時点で、a
の「効果」は b
が持っている「効果」に置き換えられ、元々持っていた効果は雲散霧消してしまうのである。「ルーン文字」に「過去の記憶」はない。常に最新の「効果」しか保つことができないのである。
第一の成功 : 一時的な「ルーン文字」
そこで次のように考える。まず a
の持っている「効果」を、一時的に別の「ルーン文字」を用いて退避させておく。それから a
の「効果」を b
の「効果」で置き換え、次に b
の「効果」を、あらかじめ退避させておいた a
の「効果」で置き換えるのである。
#include <stdio.h> int main() { int a = 3, b = 2; printf("a = %d, b = %d\n", a, b); int tmp = a; a = b; b = tmp; printf("a = %d, b = %d\n", a, b); return 0; }
今度は
a = 3, b = 2
a = 2, b = 3
とちゃんと入れ替わった。
第二の失敗
では、いよいよ「呪文」を作ろう。「効果」を入れ替える部分を新たな「呪文」として定義する。
#include <stdio.h> void swap(int, int); int main() { int a = 3, b = 2; printf("a = %d, b = %d\n", a, b); swap(a, b); printf("a = %d, b = %d\n", a, b); return 0; } void swap(int x, int y) { int tmp = x; x = y; y = tmp; }
a = 3, b = 2
a = 3, b = 2
おや ? 入れ替わってないじゃないか。
その原因は、「呪文」に何を書き添えたかにある。実はこの「呪文」のままでは、「呪文」に書き添えたものは「『ルーン文字』の『効果』」であって「ルーン文字」そのものではないのである。そしてこの「呪文」は void
型、すなわち「魔法」本体には何も返さない。なので、元々の a
と b
には何の影響も与えないのである。
どうにかしてこの「呪文」に、「ルーン文字」そのものを書き添えてやることはできないだろうか ?
第二の成功 : 「ルーン文字」そのものを「呪文」に書き添える
#include <stdio.h> void swap(int *, int *); int main() { int a = 3, b = 2; printf("a = %d, b = %d\n", a, b); swap(&a, &b); printf("a = %d, b = %d\n", a, b); return 0; } void swap(int *x, int *y) { int tmp = *x; *x = *y; *y = tmp; }
まず、「呪文」を変更して、「ルーン文字」そのものを書き添えられるようにする。普通の「ルーン文字」は他の「ルーン文字」や「呪文」の「効果」だけを受け入れるが
void swap(int *x, int *y) { ... }
の x
と y
は「ルーン文字」そのものを受け入れることができるのだ。それらの「効果」だけを呼び出すには *x
, *y
のように書く。
そして、「魔法」本体側でこの「呪文」を使用するときに
swap(&a, &b);
と書いたのは、a
, b
と書くと「効果」だけが呼び出されるので、「ルーン文字」そのものを呼び出すために &a
, &b
と書いている。
この辺は C 魔法の中でもかなり高等な技術で、C 魔法使い見習いがよく躓くところである。今回の要点をまとめると
- 「ルーン文字」は「過去の記憶」を持たないので、必要に応じて別の「ルーン文字」に「効果」をコピーする必要がある。
- 「ルーン文字」そのものを表す「ルーン文字」が使える。「ルーン文字」そのものを表す「ルーン文字」
x
について、その「効果」を呼び出すときは*x
と書く。 - 通常の「ルーン文字」
a
で「効果」ではなく「ルーン文字」自身を呼び出すときは&a
と書く。