• ベストアンサー

c言語のメモリの確保について

c言語で変数を宣言したり、領域を確保したりする場合に、メモリ上のこのアドレスに領域を確保する、といったように場所を指定することはできるのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • FM-8
  • ベストアンサー率39% (65/164)
回答No.10

#3,#6です. ちょっと混乱させたかもしれません.すみません. 目的が明確ならば,もうすこし的確にアドバイス出来るですが.(言い訳です.) >データを検索する場合、例えば、構造体aを配列でa[10]と宣言し、それら10個を順に検索していく場合と、 >mallocしながらチェーン状つなげられた構造体を10個検索していくのでは、10個アクセスしきるのにかかる時間は同じということでしょうか? ご質問を私がただしく理解しているかわからないので不安ですが, 例えば,   unsigned char a[10][100]; unsigned char *b[10]; とやれば,どちらも10個の文字列,(aの方は長さが100に制限されています.)が定義できます.   bの方は,格納先をmallocなどで確保しなければなりませんが,必要なだけ確保すれば良いので,メモリ的には効率的です.また,これら2つの使い方ではスピードの差異はないと思います.  それが,(ランダム アクセス)Random Access と言うことです.  これが,ハードディスクやCDだと,メモリの格納場所が物理的に離れていると,ディスクの回転を待たなければならない場合が多々あります. 先般の回答で,「先頭から...」と書いてのは, リスト構造の場合は,先頭からたどっていかないと その先がわからないと言うことです. 今回の例の*b[10]は,リストではありませんので, 先頭から追わなくても可です. ただし,個数は,10に制限されています. たとえば,ファイルのディレクトリ構造というのは, リスト構造です. ファイルを特定するには,フルパスを指定しなければなりません.そして,ルーとから順番に追っていきます. これに対して,リストでないのは,初期のMS-DOS1.0やCP/Mです.固定ディレクトリ方式であって,簡単です.そのかわり,格納できるファイルの量によってシステムをいちいち変えなければなりません.リスト構造というのは極めてスマートなデータ構造なんですよね. 私もリストに詳しいわけではないので,専門家が見たら怒るようなことを書いてしまっているかもしれません. どなたかもご質問のように, 解決したいアプリケーションの目的を明確にした上で,再度ご質問されればいいと思います. 私の結論としては,ハード資源を使わないのであれば,「絶対番地のアクセス」をせずとも「もっとスマートにプログラムは書けます」ということです.

taurus4
質問者

お礼

ありがとうございました。ランダムアクセスってそういうことだったんですね?疑問は解決したんですが、皆さんご指摘のように、本来の質問とかけ離れてしまいましたので、これで終わりにしたいと思います。ありがとうございました。

その他の回答 (9)

  • ara_ara
  • ベストアンサー率35% (124/348)
回答No.9

#7です。 >素人なので教えていただきたいんですが、そのような禁止領域アドレスってのはどうやって把握するのでしょか? 割り込みベクタはCPUに依存していますので、8086のCPUについて調べてみてください。 BIOSデータ領域は、IBM PC-ATのBIOS仕様を調べてください。 DOS領域についてはMS-DOSの情報になります。 これらを調べられないなら、変則的なメモリアクセスは控えるべきです。 >>もし連続したまとまった領域が必要なら、malloc()で大きな領域を確保すればいいだけです。 >その大きさが不定だから困っているんですが、なにか方法ありますかね? どんな状況かはわかりませんが、それならそれで、とりあえず例えば50KBをmalloc()するとかすればいいのではないんでしょうか?

taurus4
質問者

お礼

ありがとうございました、メモリアクセスについては自分にはちょっと敷居が高すぎたように思います、勉強したいと思います。 mallocについてもtatsu99さんの言うようなことができると思ってなかったので、質問してしまいました。済みませんでした。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.8

>データを検索する場合、例えば、構造体aを配列でa[10]と宣言し、それら10個を順に検索していく場合と、mallocしながらチェーン状つなげられた構造体を10個検索していくのでは、10個アクセスしきるのにかかる時間は同じということでしょうか? 同じと考えて問題ありません。検索に要する時間の問題は、どこのメモリを参照しているか(つまり飛び飛びの離れたメモリと連続したメモリ)よりも、参照回数が何回かかるかのほうが影響が大きいです。 例えば10000個の配列を順に頭から検索すると平均5000回の検索回数になりますが、バイナリーサーチを行った場合は、10数回程度で済みます。 従って、検索の方法を再度考え直す方法が必要かと思います。 >もし連続したまとまった領域が必要なら、malloc()で大きな領域を確保すればいいだけです。 >その大きさが不定だから困っているんですが、なにか方法ありますかね? まず、ある一定の要素分(例えば1000個)をmallocします。つぎに、1001個目で、足りなくなったときは、今の数(1000)+1000個のメモリをmallocします。そして、前のメモリを新たなメモリへコピーします。そのあとで、前のメモリを解放します。 何れにしろ、問題点が最初の質問と離れてきていますので、一旦締め切って、再度質問されてはいかがでしょうか。そのときは、OS名(solaris)は明記するようにして下さい。

taurus4
質問者

お礼

>例えば10000個の配列を順に頭から検索すると平均5000回の検索回数になりますが、バイナリーサーチを行った場合は、10数回程度で済みます。 なるほどぉ、勉強になります。バイナリーサーチというものを調べて見たいと思います。 また、mallocの仕方(はじめとりあえず適当に確保しておいて、広げたくなったら別の場所で)もべんきょうになりました。詳しいやり方はわかりませんが、調べてみたいと思います。ありがとうございました。

  • ara_ara
  • ベストアンサー率35% (124/348)
回答No.7

>でもMS-DOSでも不適当なアドレスにセットしようとするとエラーになり、強制終了してしまうんですかね? 「不適当なアドレス」が何を意味しているのかわかりません。 MS-DOSにはメモリプロテクトの機能はありませんので、ポインタに絶対アドレスをセットしてアクセスすることは可能です。 但し、当然のことですが、割り込みベクタテーブルや、BIOSデータ領域、DOS領域、スタック領域などを不適切な値に書き換えるとうまく動作しません。 また、ヌルポインタはダメです。 >OSはSolarisとかっていうやつです Solarisでは無理です。 >自己参照構造体をたくさんつなげていく場合に、それらの場所が離れ離れになっていると、... 関係ないと思われます。 もし連続したまとまった領域が必要なら、malloc()で大きな領域を確保すればいいだけです。

taurus4
質問者

補足

ありがとうございます。 >但し、当然のことですが、割り込みベクタテーブルや、BIOSデータ領域、DOS領域、スタック領域などを不適切な値に書き換えるとうまく動作しません。 素人なので教えていただきたいんですが、そのような禁止領域アドレスってのはどうやって把握するのでしょか? >もし連続したまとまった領域が必要なら、malloc()で大きな領域を確保すればいいだけです。 その大きさが不定だから困っているんですが、なにか方法ありますかね?

  • FM-8
  • ベストアンサー率39% (65/164)
回答No.6

#3です. >MS-DOSでも不適当なアドレスにセットしようとするとエラーになり、強制終了してしまうんですかね? 最近,MS-DOSで動かしてないので何とも言えませんが, Windows のDOSプロンプトや,コンソールプロンプトでも 結局は,8086系CPUのプロテクトモードで動いていますので ,エラーは出ると思います. やるとしたら,それらのCPUを純粋MS-DOSモードで動かせる フロッピーかなにかのMS-DOS5.0 システムディスクを作らないと... そのモードは,Pentiumも8086モードで動きますので, 32ビット演算も出来ませんが. また,メモリも,640KByteしか使えません. そんなのに意味は無いですね.たぶん. >自己参照構造体をたくさんつなげていく場合に、それらの場所が離れ離れになっていると、例えば、それらを検索したりする場合などに時間がかかってしまうと思ったからです。 メモリは,D-RAMとか言いますが,それは, Randam Access Memoryという意味です. つまり,メモリの番地によらず,アクセススピードは同一です. 時間がかかると言うことは無いでしょう. もしかして,メモリをひとつづつ増やして検索しようとしてますか? そう言うときは,「リスト構造」といって,次に参照する構造体のアドレスを入れておくんですが.それを使って, チェーン状にアクセスしていきます. たしかに,先頭から検索しないと番地は特定できませんね.真ん中にぽつんとある時など先頭からいかないといけません. たぶん,絶対番地をアクセスするよりも, データ構造を工夫してスピードを上げた方がた方がいいと思いますよ.

taurus4
質問者

補足

ありがとうございます。 >つまり,メモリの番地によらず,アクセススピードは同一です. につてもう少し教えていただきたいんですが、 データを検索する場合、例えば、構造体aを配列でa[10]と宣言し、それら10個を順に検索していく場合と、mallocしながらチェーン状つなげられた構造体を10個検索していくのでは、10個アクセスしきるのにかかる時間は同じということでしょうか?

  • ara_ara
  • ベストアンサー率35% (124/348)
回答No.5

MS-DOSでは、ポインタ変数に適当なアドレスをセットすれば、変数領域としてアクセス可能です。 (プログラマの責任で、適切なアドレスを利用する必要はあります) しかし、WindowsやUnixなどでは、OSがプロセスに利用可能なメモリを割り当てますので、勝手なアドレスにアクセスすると、例外エラーやSegmentation Faultのエラーになり、プロセスは強制終了させられてしまいます。

taurus4
質問者

お礼

ありがとうございました。でもMS-DOSでも不適当なアドレスにセットしようとするとエラーになり、強制終了してしまうんですかね?

  • abayama
  • ベストアンサー率48% (38/79)
回答No.4

taurus4さんが書きたいプログラムは、組み込みプログラムでしょうか? WindowsやLinux等の通常のOSでは、#1,2,3さんの回答の通りで出来ません。スタック領域から取るとか、ヒープから取る、という程度の制御しか出来ません。 組み込みOSの場合だと、一定のメモリ領域をリンカ等で指定してやり、そこの領域から動的にメモリを確保するライブラリを記述したり、などとすることは可能です。

taurus4
質問者

お礼

すみません、素人なので分からない言葉ばかりで、回答できないんですが、OSはSolarisとかっていうやつです。ありがとうございました。

  • FM-8
  • ベストアンサー率39% (65/164)
回答No.3

C言語の仕様という点からすると,メモリの絶対番地 にデータを格納するというのは出来ないと思います. ポインタに(絶対番地の)アドレスをセットし,値を入れれば出来そうですが,OSはたいてい「マッピング」といって,論理アドレスからメモリのアドレスを算出するときに 適当に変えてしまいます. そのアドレスが変なアドレスだと,「致命的なエラー」を 検出して,プログラムを停止させます. メモリの絶対番地にアクセスする目的が, スクリーンやプリンタ,コミュニケーションポート(RS232C)などのハード資源に直接アクセスする事であれば, お行儀の良いプログラムとしては,システムの提供する API(アプリケーション用の関数)を利用した方がいいでしょうね. スピードは落ちますが,ポータビリティー(移植性)は上がります. そうはいっても,DOSの延長線でプログラムしたい人は います. たとえば,DJ-GPPというフリーの処理系では, スクリーンを特定の論理アドレスに割り当ててくれます. そのアドレスをたたけば,1670万色の点々を打つことが出来ます. みなさん既にご指摘のように, Cの仕様の中には,「メモリ上のこのアドレスに領域を確保する、」は無いと言うことですが, 処理系によっては「抜け道」も用意されています. 処理系を具体的に指摘してみてはいかがでしょうか. 特に,ハードに密着した処理系(ROM化するのが前提のもの) ではたいていご質問のようなことは出来るようになっています. しかし,VC++などの一般的なコンパイラでは難しい気がします.

taurus4
質問者

お礼

素人なもんで、回答していただいたような専門的な目的のためではないのですが、勉強になりましたありがとうございます。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

通常は、malloc関数などでメモリを確保した場合、そのアドレスがOSから返されるので、呼び出し側から指定することは出来ません。 「メモリ上のこのアドレスに領域を確保する、といったように場所を指定する」必要があるために、このような質問をされたのだと思いますが、何故、そのように指定する必要があるのかが、私にとって非常に興味があります。できましたら、何故、このような質問をされたのか教えていただけませんでしょうか。

taurus4
質問者

補足

自己参照構造体をたくさんつなげていく場合に、それらの場所が離れ離れになっていると、例えば、それらを検索したりする場合などに時間がかかってしまうと思ったからです。

  • neKo_deux
  • ベストアンサー率44% (5541/12319)
回答No.1

処理系によると思います。 Windows、Unixなどの最近のOSでは、メモリ全体をOSが管理していますから不可能です。 あるアドレスを使用するプログラムが2種類あると、同時には動作できませんから、シングルタスクになるでしょうね。 c言語の基準に準拠した標準的なmalloc関数などには無いはずですが、MS-DOSなんかではアセンブラなんか書ければ可能だったハズ。

taurus4
質問者

お礼

ありがとうございます、DOSだとできるんですか、参考になりました。

関連するQ&A