4: 2007-03-25 (日) 13:24:32 |
現: 1970-01-01 (木) 18:00:00 |
- | ポインタ | |
| | | |
- | | |
- | まずは、「C言語には、メモリに直接アクセスする命令はない!」と理解する。 | |
- | | |
- | たとえばC言語に「write_mem8(0x1234,0x56」なんて命令があればいいのだが・・・ | |
- | | |
- | そこで、C言語では''ポインタ''というものを使って、メモリの番地を直接扱えるようになっている。 | |
- | | |
- | たとえば | |
- | char p; | |
- | p = 0x41; | |
- | | |
- | なんてしたとしよう。 | |
- | | |
- | ここまではまあ、大抵の人は意味解るはず。 | |
- | | |
- | さて。ここでこう考えてみる。「pの中には0x41が入っている。じゃ、0x41が入っているのって、どこ?」ということ。 | |
- | | |
- | 「はぁ? 変数pだべさ?」と。これは正解。では、「その変数pって、どこ?」と、こう続く。 | |
- | | |
- | 「変数pは変数pだろう!」というわけには行かない。なぜなら、コンピュータではどんなデータも変数もメモリに記憶されている。記憶されているのがメモリである限り、そこにはかならず「何番地か?」という概念が付いてくる。 | |
- | | |
- | (ちなみに、これを意識する必要がないという場合のほうが多い。そういう場合はもちろん意識しなくてもよい。) | |
- | | |
- | | |
- | **やりたいことを先に考えてみる [#t780ebd3] | |
- | C言語とて普通の場合はアドレス変数(ポインタ)などほとんど使わない。というか、使わなくても大抵のことは実現できることを忘れてはいけない。 | |
- | | |
- | COLOR(blue){''「ポインタを理解していないとCは使えない」''は正しくない。代替手段を工夫したり関数を探してきたりすれば大抵解決できることを忘れてはいけない。もしC言語の入り口でポインタに遭遇し、運悪く躓いてしまったら「とりあえずはシカト」で先に進むことをお勧めする} | |
- | | |
- | さて、こういう場合を考えてみよう。 | |
- | -「VRAMを直接操作して、画面に文字を書きたい」 | |
- | --AT互換機の場合、メインメモリの一部にVRAMが接続されている。これはグラフィックモードはもちろんだが、テキストモードでも同じである。(普通はB800番地〜BFFFF番地の範囲) | |
- | --C言語のprintf等を使って文字を出力することは可能だが、画面にAA(アスキーアート)で絵を書きたいなんて場合は直接書いたほうがずっと楽だし応用も効く。 | |
- | --とにかく、0xB8000に0x41を、0xB8001に0x42を、0xB8002に0x43を・・・と書き込みたいと考える。 | |
- | | |
- | さてその場合。C言語でできるだろうか? | |
- | | |
- | ふと想像すると、C言語のどこかに 「 writemem(0xB8001,0x42);」 なんて命令がありそうである。 | |
- | | |
- | ・・・しかし残念ながら、そんな命令はない。(少なくとも標準関数では。) | |
- | | |
- | では、Cではある番地にある値を代入することはできないのだろうか?。あるいは「そういう操作や考えをしてはいけない言語」なのだろうか??? | |
- | | |
- | そこで登場するのが、アドレス変数(ポインタ)である。 | |
- | | |
- | まずはとにかく、以下を見てほしい。これはまったく同じ結果になる。 | |
- | | |
- | writemem(0xB8001,0x42); ←妄想した関数。こんなのは実際にはない。しかし | |
- | この関数がもしあったなら、なにをしてくれる | |
- | 関数かは解るだろう。メモリの0xB8001番地に、 | |
- | 0x42を書き込めと命令している。 | |
- | | |
- | char *p; ←上記の妄想関数と同じことをC言語のポインタ | |
- | p = 0xB8001; でやろうとするとこうなる。まずはとにかく、 | |
- | *p = 0x42; この3行で一組と考えるとわかりやすいかも。 | |
- | | |
- | | |
- | 逆を考えてみよう。 | |
- | メモリの0xB8003番地の値を読み出して、もし0x01なら0x30に書き換えする。それ以外だったらそのまま。なんて処理を妄想する。 | |
- | | |
- | char c; ←お解りになるだろうか?。readmemとwritememと言う | |
- | c = readmem(0xB8003); 妄想関数で処理してみた。妄想関数はともかく、 | |
- | if(c == 0x01){ ここがどういう処理をしているかは解るだろう。 | |
- | writemem(0xB8003,0x30); | |
- | } | |
- | | |
- | char *p; ←上記の処理をポインタを使ってやってみた。 | |
- | p = 0xB8003; こんなふうに並べると、だんだん解ってこない? | |
- | if(*p == 0x01){ (とにかくこれは一種のパターンとして一旦理解 | |
- | *p = 0x30; しちゃうと早いと思う) | |
- | } | |