• ベストアンサー

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

  • C言語のメモリ領域確保

    ポインタ変数ををmain関数で宣言し、関数test()にて必要分だけ領域確保してそのアドレスをmain関数のポインタ変数に渡して利用することは可能でしょうか。 (サイズのわからないテキストデータを、十分に大きな配列に入れるのではなく、関数でメモリを動的確保して無駄の無い配列に入れたい等) C言語ではやはり無理で、構造体のリストにするのが一番でしょうか。 初歩的なことで申し訳ありませんがどなたかお願いいたします。

  • c言語のmalloc関数、またrealloc関数

    c言語のmalloc関数は確保するメモリの領域を、配列としてのみしか処理出来ないのですか。 つまり、malloc関数で確保したメモリの領域を変数、また多次元配列、また構造体としては処理出来ないのでしょうか。 c言語のrealloc関数は以前の確保したメモリの領域から、確保し直したメモリの領域の場所が変わるかもしれないという事ですが、この場合の場所が変わるという意味は、メモリの領域のアドレスが変わるという事でしょうか。 また、以前の確保したメモリの領域に代入していたデータが使用出来なくなるという事でしょうか。

  • 動的なメモリ領域の確保

    double型変数5個分のメモリをmalloc関数により確保し,その確保した要素のアドレスを表示するように,プログラムを作る問題で、 (注)に「 %pで表示するためには,double型へのポインタ(double *)をvoid型へのポインタ(void *)にキャストする必要がある.」と書かれていたのですが、どういうことでしょうか? 以下のようでいいのでしょうか? #include<stdio.h> #include<stdlib.h> #define COUNT 5           // 動的に確保するメモリ領域数を示すマクロ定数の定義 int main(void) {  // 動的に確保するメモリ領域のアドレスを保持するポインタ変数の宣言  double * pointer;  int i;                  // for文で使用する変数の宣言  // int型変数5個分のメモリ領域を確保  pointer = (double *)malloc(sizeof(double) * COUNT);  if(pointer == NULL) {        // メモリ領域の確保が失敗した場合   printf("メモリ領域を確保できませんでした.\n");   exit(1);                // プログラムの終了  }  for(i = 0; i < COUNT; i++)   printf("%d番目のアドレスは%pです.\n", i + 1, pointer + i);  free(pointer);            // 確保したメモリ領域の解放  return 0; }

  • C言語におけるローカル変数が使用するメモリについて

    例のようなC言語のプログラムを動かした場合、 確保されるメモリ領域はどうなるのでしょうか。 例 #include <stdio.h> int main(void) { int a = 0; } このとき、変数aはint型なのでスタック領域に4バイトのメモリが確保されると理解しています。 と同時にaという変数名と確保されたスタック領域の番地を紐づけるようなメモリがどこかに確保されるのではないかと思ってるのですが、この理解で正しいでしょうか。 またその場合は変数aの番地はどの領域に確保されるのでしょうか。 ご教示お願いいたします。

  • 動的確保について

    こんばんは。プログラミングについてお聞きしたい事があり 投稿させて頂きました。初心者なので見当違いでしたら申し訳 ありません。 現在、C言語でプログラムを作成しているのですが、メモリの 動的確保をする際、確保する領域の先頭アドレスを指定するという ことは出来ないのでしょうか。 現在はmallocを使用して領域を確保していますが、実験の都合上、 どうしても自分で確保すべき領域を指定したくなりました。 調べても分からないのでもしノウハウをお持ちの方がいましたら 教えて頂けますでしょうか。 宜しくお願い致します。

  • アセンブラでのメモリの動的確保について

    自作コンパイラのために最近NASMを使ってアセンブラの勉強を始めたものです。 メモリ領域の確保のためにNASMでは buffer: resb 64 と宣言しますが、C++でのchar* buffer=new char[size]; のような、動的なメモリ領域の確保の記述は可能でしょうか? 普段はC++を主に使っているため、見当違いな質問かもしれませんが、よろしくお願いします。

  • C/C++言語のメモリについて

    C言語でメモリを2種類?に分けると、スタックとヒープがあります。 ヒープは mallocなどで確保し、freeで解放しますがスタックは解放する必要がありません。 そのスタックは通常、何バイトまで可能なのでしょうか? あと関数外のファイルの先頭に int[1000000];とした場合、このメモリはmallocで確保していませんが、 どこに作られるのでしょうか? 私のパソコンはメモリが2GBでWindows2000ですが、CやC++で最大、何バイトまでメモリが使えますか? また、一番多くメモリを確保できるなら、OSはなんでも構いません。 解釈等も間違っていたらご指摘していただきたいです。

  • 動的メモリ確保の外部関数

    画像処理関係のプログラムを作成しているのですが(C言語で)、動的にメモリ確保をすることが頻繁にあります。 そこで、どんな型(int,char,double,etc..)の場合でもメモリ確保できるような、1つの外部関数を作成したいと考えています。 例えば、 int Memory(引数) { 型宣言; int型の動的メモリ確保; char型の動的メモリ確保; double型の動的メモリ確保; return 0; } イメージでは、上のような感じです。 もしかして、このような考えは、不可能でしょうか? どなたか良いアドバイスがあれば、ご教授ください。 よろしくお願いします。

  • c言語のメモリリークについての質問

    c言語のメモリリークについての質問 c言語初心者のため、メモリリークについて質問させていただければと存じます。 下記のコードで、 char* char_p = "char1"; char_p = "char2"; // ←メモリリーク? 2行目の部分は、 "char1"のメモリ領域が確保されたままで、解放できなくなってしまうので、 メモリリークを起こして問題な気がするのですが、実際はどうなのでしょうか? よろしくお願いいたします。

  • C言語 関数の戻り値と自動変数

    かなり基礎的な質問になるのですが、疑問に思うことがあり、質問をさせていただきます。 関数内で宣言した変数を戻り値として使う場合ですが、ポインタなどではなく実体の場合でも、静的変数として宣言をしたほうが良いのでしょうか? 現実的に考えると、プログラムが関数から出て、呼び出した側の関数が戻り値を受け取るまでの瞬間に、その領域が書き換えられる可能性は極めて低いと思うのですけど、C言語の仕様としてはどうなのでしょうか? 関数内で宣言した戻り値に使う変数には、必ずstaticをつけた方が良いのでしょうか? もしおわかりでしたら教えて下さい。

専門家に質問してみよう