- ベストアンサー
ポインタで、実装メモリの先頭から100バイト分参照してみたい
いつもお世話になります。 Cの質問です。 ポインタの勉強中なのですが、ポインタを用いて、実装メモリの先頭から100バイト分を参照してみたい、と思いました。 先輩が言うには「メモリの先頭領域にはメモリのメーカーとか、文字コードが順番に入ってるよ」とのことなのですが、どうにもプログラムが作れません。 mallocでは、どうやら「コンパイル時にメモリ領域を確保する」らしく、指定したメモリ位置(つまりアドレス0)からxxバイト分確保することはできないようです。 私が試しに書いてみたソースは以下になります。 #include<stdio.h> #include<stdlib.h> int main(void){ int i; char *p; p = (char*)malloc(sizeof(char) * 100); for (i=0;i<100;i++){ printf("%c",*p); p++; } return (0); } アドバイスでもかまいませんので、ご指導いただけたらと思います。 よろしくお願いいたします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
昔のMS-DOSであれば何も考えずにC言語で物理アドレスを指定しさえすれば 覗けたと思いますが、Linuxの場合、ブート時にプロテクトモードになってしまうので、”ポインタ”でアクセスするのは厳しいかと思います。 ポインタの勉強にはなりませんが、 /dev/mem を使えば良いかと。 どうしても「ポインタの勉強」というのであれば、/dev/memをmmapでしょうか・・・。
その他の回答 (4)
- tokichim
- ベストアンサー率42% (88/205)
ポインタの勉強のためにメモリを覗く、というだけなら以下のようなプログラムくらいでいいんじゃないかと。 ちなみに、プログラムに埋め込まれた文字列の置いてあるメモリの中をポインタを使って読み出す、というプログラムです。 出力は"アドレス: 文字データ値 文字"となります。 #include<stdio.h> const char SampleStr[] = { "This is a pen." }; main(){ _int i; _char *p; _p = &SampleStr[0]; // 文字列の先頭をポイント _for( ; *p != '\0'; p++ ) { __printf("%p: %02X %c\n", p, *p, *p); _} _return (0); } (_はインデントの代わり)
お礼
ご回答ありがとうございます。 mainの部分の >main(){ という書き方と、 >for( ;~~) という初期化式のない書き方は初めて見ました。 勉強になりました。 ありがとうございます。 ※この場を借りてみなさまにお礼を申しあげます。 素朴な?疑問に丁寧に回答してくださり、ありがとうございます。 ポイントは、私の主観で、「回答・勉強になった順番」にさせていただきます。 ご了承ください。 それでは、皆様もこれからもよいご回答をつづけてください。 ありがとうございましたm(_ _)m
- jacta
- ベストアンサー率26% (845/3158)
> 先輩が言うには「メモリの先頭領域にはメモリのメーカーとか、文字コードが順番に入ってるよ」とのことなのですが、どうにもプログラムが作れません。 もしかして、メモリカードとか、そういったものの話をしていませんか? だとすると、メモリの中身がCPUのアドレス空間には直接マッピングされるわけではないので、適切なコマンドを送るなどして制御しなければなりません。
お礼
ご回答ありがとうございます。 >もしかして、メモリカードとか、そういったものの話をしていませんか? メモリカード・・私の知識不足でうまく理解できないのですが、会社のPCは、マザーボードにCPUとメモリが刺さっている、通常の構成だと思います。 先輩が言っていたのも、この"マザーボードのスロットに刺さっているメモリ"の先頭部分、のことだと思います。(昔、先輩がやったときは)「NECなんたらかんたら・・とか書き込まれてるんだよな」というようなことを言っていましたので。 >メモリの中身がCPUのアドレス空間には直接マッピングされるわけではない 単純に、ポインタに0を設定したからといって、それが実装されているメモリの0番地を指す訳ではない、ということでしょうか。 勉強になります。 ありがとうございます。
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
p = 0; としても、コンパイルではエラーにはならないはずなのですが(もしかしたら、警告は出るかもしれません) あとは、 p = (char *)0; くらいでしょうか。 ただし、実行時にエラーが出る可能性はあります。 もともと、ポインタに「0番地」を設定することは互換性の点で問題があります。(大抵は可能ですが) というのも、ポインタに、「0を代入」「0を比較」というのは、NULL の代入や NULL との比較になります。 実は、この関係で、0 だけは、p = 0 とした後の、p が、0 番地をポイントしているという保証がないのです。 この点は知識として持っておくと良いかもしれません。 また、特にマルチタスクをサポートするOSでは、アプリケーションから見た「0番地」と実装メモリの「0番地」は必ずしも一致しません。(というか別です) このあたり、何か誤解がありそうな気はします。
お礼
ご回答ありがとうございます。 >p = 0; としても、コンパイルではエラーにはならないはずなのですが(もしかしたら、警告は出るかもしれません) はい。私のミスでした。。。 コンパイルは通りますが、実行時エラーで落ちます。 単に0を入れてしまうと、NULL扱いになってしまうのですね。 試しに、p=(char*)1; にしてみましたが、やはり実行時エラーで落ちました。 >アプリケーションから見た「0番地」と実装メモリの「0番地」は必ずしも一致しません。 勉強になります。 有益な情報をありがとうございます。
- shimix
- ベストアンサー率54% (865/1590)
なお、OSが書かれていませんが、アプリケーションから実装の物理メモリへの直接アクセスが許可されているOSですよね(OSによっては制約があるかもしれないので)。またアプリでの0番地が物理メモリの0番地に対応しているという前提でいいですね(アプリのロード時にあれこれしてくれるOSもありますから)。 「実装メモリの内容」ですから、mallocする必要はありません。いったんコピーしてから処理するなら「コピー先」として確保しないといけませんが、そういう処理ではないようですので。
お礼
ご回答ありがとうございます。 会社のシステムはTeraTermでRHLinuxにSSHしてgccを使ってます。RHLinuxのバージョンまではわかりません。 家では、WindowsXPに、MinGWをインストールして、eclipseでコードを書いています。 >「実装メモリの内容」ですから、mallocする必要はありません。いったんコピーしてから処理するなら「コピー先」として確保しないといけませんが、そういう処理ではないようですので。 mallocする必要はないのですね。勉強になります。 したいのは、メモリの先頭から100バイト分を参照したいだけ、です。なぜ100バイトかは根拠はありません。とりあえず、そのくらいのメモリスペースを覗いてみて、何が書かれているのかを確認したい、というだけです。 いまは、ポインタの使い方、ポインタで出来ることを勉強中です。 「コピー」となると、strcpy関数なのでしょうか。 いろいろ調べてみましたが、文字列長をチェックせずにコピーしてしまうため、バッファオーバーフローになる可能性があるため使用しないほうが望ましい、という知識を身につけることができました。 ですが、これで参照するにはどうすればよいのかわかりません。。。 単純に、ポインタに、 p=0; として(メモリの0番目を指定しているつもり)しまうと、コンパイルエラーになるので、どうしたものか・・と悩んでいます。。 printf("%c,%d",*p,p); で、それぞれ一文字と、そのアドレスが表示されるのは理解したのですが、メモリの先頭アドレスを指定して表示するにはどうしたらいいのかがわからず詰まってしまっています。 追加でアドバイスいただけましたらよろしくお願いいたします。
お礼
ご回答ありがとうございます。 >昔のMS-DOSであれば~覗けたと思いますが、 >Linuxの場合、ブート時にプロテクトモードになってしまうので、”ポインタ”でアクセスするのは厳しいかと思います。 なるほど。 先輩も、「Windows3.1が出たときにびっくりしたよ」という超古株なのでそのときのことを言っていたのかもしれません。 (本来ならばPGではなく管理職についている年齢なのですが、PGの方が好きということで敢えてPGを続けている方です。気さくなのでみなさん「先輩」と呼んでいますが・・) みなさまのおかげでかなりスッキリしました。 万能といわれるC言語にも、限界はあるのですね。 (限界というか、システム側である程度限界を設定しないと、それこそバッファオーバーフローやらなにやら、なんでもできてしまいますものね) 大変勉強になりました。 Linuxはまだそれほど詳しくないのですが、/dev/memを覗いて調べてみようかと思います。 ポイントは、私の勉強になった順に、明日つけさせていただきます。 みなさま、ご回答ありがとうございました。 感謝!