• ベストアンサー

ポインターとアレー

アセンブラ言語を勉強しております。 mallocが、イマイチわかりません。 CPU内のレジスタに容量をつくるオペランドらしいというのが、わかりましたが。。。 それから派生する、 @SIZE() ポインター heap アレー string などが、何回聞いても、調べてもイマイチわかりません。 丁寧に教えていただけますか? よろしくお願いします。

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

  • ベストアンサー
  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.4

素人が思いつくまま記します。大きな課題なので、じっくりOSの本を読んでください。 MallocはMemoryAllocationすなわちOSシステムがメモリーを プログラムを読みこむためやデータを読み込むためやセットするために、そのエリアを確保する(割り当てる)こと。ポインターはオブジェクトプログラムのアドレスや変数の先頭番地を記憶するエリアや機能。C言語に限らず、Assemblerではポインターはアドレスを指すという機能と共に前面に出てくる。Basic言語は全くアドレスの考えを隠している言語です。ポインターは演算ができるので応用が広がります。アドレスモディファイというのが有ります。HeapはHeapSortというのがありますが、メモリー管理のための代表的なアルゴリズムのようです。アレーはArreyで配列のことでしょう。文字列の表現はC言語などでは配列の考えに持ちこんでいるのです。配列は要素数があり、これの上限を決めるものの、途中で増やしたい時があり、Redimとかやるときに、メモリーをMallocする必要が出てくる。Stringは文字列ですが、配列と考えると、これも文章の長さなどは一定とか限度がもうけられず、限度を越えるとメモリーを確保する必要がある。また不要になったメモリーエリアは解放して、たの用途に使わせなければならない。 OSのメモリー管理の本を読んだらどうでしょうか。数などは4バイト (32ビット)とか8バイト(64ビット)などと固定しているので考えやすいのですが、文字列や配列になると、ユーザー側がどう指定してくるか 不確定のところがあり、この処理のテクニックが(アルゴリズムが)OSでは要るようです。

takiewacky
質問者

お礼

お手数をおかけしました。 この授業は、あと残り一週間となりましたが、 期末を受けず、また別の機会にとることにしました。 お手数をおかけしました。 ありがとうございました。

takiewacky
質問者

補足

ご丁寧なお答えありがとうございます。 しかし、自分の勉強不足でもう少し伺いたいことがあります。 MallocはMemoryAllocationすなわちOSシステムがメモリーを プログラムを読みこむためやデータを読み込むためやセットするために、そのエリアを確保する(割り当てる)こと。 とありますが、そのエリアは、EAXやAX、AH,ALといったCPUにあるレジスターの内と考えてよろしいのでしょうか? ポインターはオブジェクトプログラムのアドレスや変数の先頭番地を記憶するエリアや機能。とアレーは、一組と考えてよろしいのでしょうか? また、アドレスは、CPUにあるレジスタ内に作られるのでしょうか? Mallocもレジスター内にメモリーを確保するのでしょうか? これらのメモリーは、ハードディスクやRAMではなく、CPU内のレジスターと考えてよろしいのでしょうか? 追加の質問なのですが、 mov( $41, DH ); //DH is the letter A mov( EAX, EBX ); //EBX is address of A[i] mov( DH, [ EBX ] ); // A[i] = i番目のアルファベット とすると$41=Aは、EBXとなるのでしょうか? もし、教えていただけるようなら幸いです。 よろしくおねがいします。

その他の回答 (4)

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.5

やや旧い時代の知識かもしれませんがお許し下さい。 >Mallocもレジスター内にメモリーを確保するのでしょうか? これらのメモリーは、ハードディスクやRAMではなく、CPU内のレジスターと考えてよろしいのでしょうか? 勿論内部メモリー(除くレジスター)RAM内でのことです。 「レジスター」と「メモリー」。どちらも記憶する機能がありますが、(1)読み出し書きこみのスピードが、メモリーより格段に早いものをレジスターとして設計している。(2)レジスターはビット数が少ない(3)内部メモリーのアドレスの代わりに、番号とか記号がつけられている。(4)内部メモリーのアドレスとは別系統である。(5)機械語のオペランドにレジスターを指定できるようになっている。(6)計算や処理機構がレジスターに対しても行うようになっている。(7)機械語命令指令はReg-Reg間、Mem-Reg間,Mem-Mem間、Reg内のみ、Mem内のみなどが有る。(5)(6)があるのでレジスターの存在意義がある。 (8)レジスター内のメモリーはビット並びとして考えられるとおもうので、バイト列に対して考えるアドレスと言う言葉はなじまないとおもう。 (9)シフト機能やビット演算(AND,OR,XORなど)がレジスター 演算として出てくる。(10)専用にRAMアドレスを表す、アドレスレジスターの機能を持たせることも多い。(11)メモリーの膨大化により、レジスターがアドレスを全域表すためにビット数が増加している。(12)2つのレジスターを繋いで使ったり、前半と後半を別に2つのレジスターとして使えるようになっているものも有る。(13)キャッシュメモリーよりスピードが速い。 >アドレスは、CPUにあるレジスタ内に作られるのでしょうか。 アロケーションとは何番から何番までのメモリー番地を、そのプログラムの処理の為に確保する(他には使わせない)と言うことで、アドレス番地はレジスターに載せてのみ表される仕組みのコンピュターだけでないので、質問の表現が不可。アドレスとはメモリー空間(帯域)の意味で使ったもの。 レジスターはアドレスの(先頭)番地を記憶する(載せる)器であり、 RAMのアドレス空間そのものではない。レジスターの数は20個以内程度と少ないものだと思うが、それだけに使い尽くすことはあるが、プログラマーの問題であって、記憶するプログラムやデータ量が多く、メモリーをもっと自分に使わせろ寄越せという問題とは違う。 >書いておられる機械語、アッセンブラについては、その知識がないので答えられません。ただDH is the letter AはDHレジスタにJIS(41)のAというCharacter1文字(定数」)をセットすると言う意味でしょうか。mov( DH, [ EBX ] ); // A[i] = i番目のアルファベットは配列(=文字列)のEBX文字目にAをセットと言う意味でしょうか。 mov( EAX, EBX ); //EBX is address of A[i]のEAXに付いては判らず、答えられません。この部分は間違っておればお許し下さい。

takiewacky
質問者

お礼

いろいろとありがとうございました。 基礎的なことを勉強しなおしてやり直します。

  • k-family
  • ベストアンサー率34% (180/523)
回答No.3

なるほど、HLAのことだったのですね。 こちらについては名前だけしか知りません。お役に立てそうもありません、ごめんなさい。 ちょっとwebで調べてみたのですが、参考になりそうなHPも少ないですし、英語ばかりですので、私の手には負えそうもありませんm(_ _)m

takiewacky
質問者

お礼

いろいろ調査していただいたようで、ありがとうございました。 お礼が遅くなり申し訳ございません。

takiewacky
質問者

補足

ご丁寧なお答えありがとうございます。 お時間を頂きありがとうございました。 これからもよろしくお願いします。

  • KOH_da
  • ベストアンサー率31% (161/506)
回答No.2

丁寧に教えようにも、CPUとかがわかんないと...。 たとえば、mallocっていうとC言語でおなじみです。 CPUのレジスタ内に容量を作るのではなく、 OSに対してメモリ確保をお願いする命令(っていうか関数)です。 SIZE()やheapや、アレー(アレイ=配列)とかを扱うとなると、 それってホントにアセンブラなの? って思います。 どの言葉も知っていて当然の言葉なので、 あなたが勉強している環境や、 その疑問を持つにいたった文章があれば、 説明できると思います。

takiewacky
質問者

お礼

学部の先生も、本件を問題にしてるようです。 assemblerが、HLAにすりかわっているとは。。。 どうもありがとうございました。

takiewacky
質問者

補足

ご親切なご回答ありがとうございます。 お答えの一番の補足説明に記入いたしました。 私もできるだけの調べをインターネットにてしらべてみましたが、適切な答えが出ているサイトを見つけることができませんでした。なぜなら、アセンブラ言語に関するサイトは、8086関係または、.asmに関係しているようなのです。しかし、.hlaというのは、どのサイトにも表記は、無かったので、頭を抱えております。 しかし、コンパイルするときに、hla assembler(コンパイラーのようなもの)、microsoft assembler, version 6.15というのを使っているようです。 お力を貸していただければ幸いです。 よろしくお願いします。

  • k-family
  • ベストアンサー率34% (180/523)
回答No.1

普通、mallocはmemory allocationで、メモリエリアを確保する命令(疑似命令)のことだと思います。もし、 >CPU内のレジスタに容量をつくるオペランドらしい だとするとかなり特殊な命令系統を持ったCPUのような気がします。(昔、メモリ上に仮想的なレジスタを作るというCPUがありましたが、そんな種類のものでしょうか) ということで、この種の質問は、具体的にCPUやアセンブラの名前を表示された方が回答がつきやすいと思います。

takiewacky
質問者

補足

確かに、理解不足からきているものだと思います。 只今、勉強しているのは、.asmという拡張子のアセンブラでは、ないのです。 .hlaという拡張子のコードをメモパッドで作成し、コンパイルしてから.asmや.exeなどのドキュメントができるという不思議なアセンブラを勉強しております。 ハイレベルランゲージを勉強した友達からは、君が勉強しているのは、本当の意味でのアセンブラではないと指摘されたことがあります。 また、手違いで取ってしまった科目なので、C/C++または、javaなど(当然ながら、DOSの知識などは、ありません)の言語の知識の無いままの勉強なので、自分の言っていることが専門知識があるかたら見るとおかしなことかもしれません。 本文では、上記のことに触れておりませんでした。 よろしくお願いいたします。

関連するQ&A

  • C言語、配列とポインタとアスタリスクの関係

    ちょっと行き詰まっています。 苦しんで覚えるCで勉強しているのですが、まさに苦しんでいます。 http://9cguide.appspot.com/19-01.html #include <stdio.h> #include <stdlib.h> int main() { int i; int *heap; heap = (int *)malloc(sizeof(int) * 10); if (heap == NULL) exit(0); for (i = 0;i < 10;i++) { heap[i] = i; } printf("%d\n",heap[5]); free(heap); return 0; } int *heap; ここで int ポインタを宣言しています。 heap = (int *)malloc(sizeof(int) * 10); ここでヒープを確保しています。(int *) のキャストも sizeof(int) も理解できました。 for (i = 0;i < 10;i++) { heap[i] = i; } まず1点目の疑問はここです。 変数 heap は「ポインタ変数」です。それでいて配列です。 ポインタ変数は、プログラムの文中で通常の変数として使うときには「*heap」のように先頭にアスタリスクを付けなければならかなったと記憶しています。 アスタリスクなしの「heap」はアドレス格納用の変数ではないでしょうか。 printf("%d\n",heap[5]); そして、その疑問をよそに、この命令が成り立っているようです。 画面上に出される結果は「5」であり、変数「heap」がただの配列として機能しているように見えます。 この printf 次のように書き換えると、エラーが出てコンパイルできませんでした。 書き換え実験1 printf("%p\n",*heap[5]); アスタリスクを付けて、通常の変数として扱い、受ける方も「%d」から「%p」に書き換えてアドレスを表示してみようと思ったのですが、 「「pointer」を付け忘れています。」というエラーが表示されました。 書き換え実験2 printf("%p\n",heap[5]); 受ける方を「%d」からポインタを受ける「%p」にしましたが、変数の方はアスタリスクなしです。 すると、結果はアドレス「00000005」が返ってきました。 (変数にアスタがないのになぜ?) 書き換え実験3 printf("%d\n",*heap[5]); これはもうめちゃくちゃですが、一応やってみました。コンパイルエラーで、 「「pointer」を付け忘れています。」というエラーが表示されました。 つまり、こういうことです。 0:printf("%d\n",heap[5]); //5 1:printf("%p\n",*heap[5]); //エラー 2:printf("%p\n",heap[5]); //00000005 3:printf("%d\n",*heap[5]);//エラー この結果から推測するに、アスタリスクはそもそも付けるとエラーになり、アドレスを表すか、そのアドレスに格納された値を表すかを切り替えるには、単にその変数を受ける「%d」や「%p」を変えるだけ、ということになるのだと思います。 mallocで返ってくるのは、ポインタ変数(の配列)だと思うので、変数のモードを切り替えるためにアスタリスクが必要なのだと思っていましたが、どこかで重大な勘違いをしているようです。 この件について、どなたか教えていただけないでしょうか。

  • ポインタの勉強中なのですが

    C言語の勉強中なのですが、ポインタのところで苦労しています。 次のような関数を作成し、main関数で実行したところ、sizeof(array)は4になりました。 main関数内で同じようにsizeof(array)を表させると配列全体のサイズが表示されますよね。 関数の仮引数として配列を書いても、実際には配列の先頭要素を指すポインタとして扱われるので 関数には&array[0]が渡され、関数は配列ひとつあたりのサイズを基に他の配列の要素のアドレスを 受け取るで合ってますよね? でもmain関数内ではsizeof(array)は配列全体のサイズを返すのに、関数内では配列ひとつあたりのサイズしか返さないのはどうしてなのでしょうか? int sum_array( int array[], int num ){ int i; int sum = 0; for( i = 0; i < num; i++ ){ sum += *(array+i); } printf("sum = %d\nsizeof(array)=%d\n",sum,sizeof(array)); return sum; }

  • C言語のポインタを理解するには

    今、自分はC言語のポインタを勉強しているのですがメモリの動きなどが想像できません・・・(なんでポインタを使うと速くなるのかなど) 聞いたり調べたところアセンブラをやると理解できるとのことでアセンブラをやろうと思ってるのですが他になにかやるべきことはあるでしょうか? 後コマンドプロンプトとPICは勉強になるでしょうか? 昔のパソコンを使ってるとパソコンがよくわかるみたいなことを聞いたのですが昔のパソコンなんて持ってないのでCUIのコマンドプロンプトを勉強すればなんかわかるかなと思って。 PICは自分で作れば勉強にもなるしそこからなんか得られるかなと思って聞いてみました。 まだパソコンをもって長くないのでいろいろと調べたのですがどうしてもよく理解できないところがあり質問におかしいところがあるかもしれないですがお返事よろしくお願いします。

  • ハードウェアアーキテクチャ?

    ハードウェアアーキテクチャ? プログラムがコンピュータで実行されるまでの筋道が知りたいです。 C言語を勉強していたのですがmalloc();などの動的メモリの部分や #pragmaを使って変数のパッキングを弄る方法、部分的にアセンブラ命令を書いて処理を軽くするインラインアセンブラなどのテクニック、 レジスタ上にメモリを確保するregisterをつけて変数を宣言する方法など、ハードウェアに近い根幹的部分のほうを知りたいです。 メモリにしろヒープ領域とスタック領域があるだとかC言語の入門書には載っていないことがよくあります。 CPUの仕組みや、メモリの動作や、根本的なことが知りたいです。 このようなハードウェア寄り?なことを専門に扱っているHPや本などありましたら教えてください。

  • malloc領域から関数ポインタ型で呼び出し

    現在C言語で,関数ポインタ型による関数の呼び出しを勉強しています. print()という関数は受け取った文字列を表示するだけの関数ですが, これを通常の関数ポインタを用いて実行したのがmain内の(*mem)("FROM POINTER.");です. これに対して後半は,mallocで確保した領域にmemcpyでprint()をコピーし, (*mem)("FROM COPIED AREA.");で実行しています. 実行環境は以下の通りです. OS:Windows7 Personal 32bit CPU:Intel Core i5 M430 統合開発環境:Visual C++ 2010 Express Edition コンパイルには成功しています. 実行すると"FROM POINTER."は表示されるのですが, "FROM COPIED AREA."は表示されず,プログラムが動作を停止してしまいます. mem = (void (*)(char*))tmp;までは実行できているようですが, (*mem)("FROM COPIED AREA.");の実行の時点で停止しているようです. またコマンドプロンプトからBorland C++ 5.5.1でコンパイルしても, 同じように動作が停止してしまいます. ただし同じプログラムでも,Cygwinからgccでコンパイルすると, 意図した通りの挙動となっていることを確認しています. コンパイラの違いによるものなのか, UNIXとWindowsの違いによるものなのか判断できずにいます. (もしくはライブラリのmalloc,memcpy辺りの実装法の違いでしょうか?) どなたかご存知でしょうか. ----------------------------------------- #include<stdio.h> #include<stdlib.h> #include<string.h> #define SIZE 512 void print(char* str){ printf("%s\n", str); } int main(int argc, char** argv){ void (*mem)(char*); void *tmp; mem = &print; (*mem)("FROM POINTER."); tmp = malloc(SIZE); memcpy(tmp, print, SIZE); mem = (void (*)(char*))tmp; (*mem)("FROM COPIED AREA."); }

  • 構造体とポインタ配列

    現在C言語の勉強をしております。 環境はwindowsXP、コンパイラはVC6.0です。 構造体と、ポインタの配列についてなのですが、 以下のような構造体が宣言されている時に、リスト構造にデータがいくつか入っているとします。 // 構造体 typedef struct address { unsigned char names[NAME_SIZE+1]; /* 名前 */ char tels[TEL_SIZE + 1]; /* 電話番号 */ struct address *prev; /* 前へのポインタ */ struct address *next; /* 次へのポインタ */ }Address, *a_pt; そのリスト構造を先頭要素か順番にポインタ配列に格納するには以下の方法ではおかしいでしょうか? /* ポインタ配列を用意する */ Address *array[MAX_COUNT]; /* top_ptは先頭のポインタです */ pt = top_pt; /* データがなくなるまで配列へ格納する */ while(pt != NULL){ array[count++] = pt; pt = pt->next; } /* 配列の最後はNULLとする */ array[count] = NULL; また、配列の中身を確認する方法としては、 printf("配列の中身:%s\n", array[0]->names); では、アドレスが表示されてしまうのかな・・と思ったら、accessViolationで落ちてしまいました・・・。 中身はどうしたらデバッグ出来ますでしょうか? そもそも、以下の2つは何か違いはありますか? Address *ptA[100]; a_pt ptB[100]; 皆さん、どうかよろしくお願いいたします。 理解不能な場合はご指摘ください。

  • CHAR型ポインタについて。

    CHAR型ポインタについて。 当方C言語初心者です。 ポインタと文字列の関係分からないことが出てきました。 参考にしている本があり、そのページに下記のソースで「const char *pc1」のポインタ変数を用意して、そこに直接文字列を代入しています。 本来、「char *pc1」はchar型のアドレスを格納するための変数のはずなのに、その変数に文字列を代入してることに疑問を感じました。 この記述の仕方は間違っていないのでしょうか?また、アドレスを格納するための変数「*pc1」に「abcdefg」の文字列はどのようにメモリ上で格納されているのでしょうか? 知ってどうなるの?みたいな質問かもしれませんが、ご教授いただけると幸いです。 #include <stdlib.h> #include <string.h> void func(void) { const char *pc1 = "abcdefg"; //←ココ char *pc2 = (char *)malloc( strlen(pc1) +1); if ( pc2 ) { strcpy( pc2, pc1 ); free( pc2 ); } }

  • ポインタによる関数への配列渡し

    林晴比古さんの「新C言語入門」でC言語を勉強している初心者です。 現在ポインタの勉強をしています。色々教科書の文例等をポインタで書くとどうなるか試しております。 上書P200練習問題2に「配列の最大値を返す(その際配列の長さを渡す)」プログラムがあり、それをポインタで渡すプログラムに直してみました。 仮引数に「maxdata」を設定し、そのアドレスを関数側に渡し、関数側ではポインタとして受け取る(そうすれば関数側からはreturnで値を返す必要がない)、と考え、下記のように書いてみました。 #include <stdio.h> void max_of_array(int n[], int len, int *ans); int main(void) { int dt[6] = {50,20,80,30,10,40}; int maxdata; max_of_array(dt,6,&maxdata); printf("最大値=%d\n", maxdata); return 0; } void max_of_array(int n[], int len, int *ans) { int i; ans = &n[0]; for (i=1; i<len; i++){ if (*ans < n[i]) *ans = n[i]; } } しかしコンパイルすると、何故か「最大値=1」となってしまいます。(正しくは80です) 他にも色々試してみましたがうまくいかず、かなり考えてみたのですがどうしても分かりません。お分かりの方、どうすれば正しくなるのが教えてください、よろしくお願いします。

  • 組み込み系C言語の学習法

    私は組み込みソフトを8年やってきました。 規模としては、白物家電をイメージしてもらうと良いです。 但し、電子レンジなど表示機能がない製品が近いかもしれません。 近いものでは、洗濯機や冷蔵庫といった感じでしょうか。 マイコンは、旧三菱の740ファミリのM38000系です。 ただソフト経験(アセンブラ)はあるものの、C言語の経験は皆無なのです。 ただし、if-else, switch-case, for, while, break, continue は充分理解できます。 何故かというと、旧三菱系のマイコンには構造化アセンブラと言って、 C言語もどきの記述ができるのです。上記文のみ特別に設けられていたのです。 それを使ってソフトを作っていたので上記分は理解できるのです。 しかし、ややこしいのがポインタや構造体や共有体や配列です。 同じことをアセンブラでもやっているはずなのです。 ポインタや構造体や共有体をアセンブラで書くとどうなるかが知りたいのです。 ここの部分が書いてある書籍がないのです。 例えば、ポインタや配列は、旧三菱系で言うとXレジスタやYレジスタを 使って行っていた作業と似てるのかなと推測できます。 同じ境遇の方で克服された方がいらっしゃいましたらアドバイスをお願いします。 また、アマゾンで下記の本を見つけました。 参考になるのでしょうか? よろしくお願いします。  ""組込み現場の「C」プログラミング基礎からわかる徹底入門""

  • reallocの使い方について

    C言語初心者です。malloc()で確保した領域をrealloc()にて拡張しました。以下、わからないことがあるので教えて下さい。 #include <stdio.h> #include <stdlib.h> int main(){ int *array1; array1=malloc(sizeof(int)*3); for(int i=0; i<3; i++){ *(array1+i)=i; } int *array2=array1; for(int i=0; i<3; i++){ printf("array2[%d]: %d\n", i, array2[i]); } array1=realloc(array1, sizeof(int)*5); for(int i=3; i<5; i++){ array1[i]=i; } for(int i=0; i<5; i++){ printf("array2[%d]: %d\n", i, array2[i]); } } 上記のソースコードでは、私が期待したのは array2[0]: 0 array2[1]: 1 array2[2]: 2 array2[0]: 0 array2[1]: 1 array2[2]: 2 array2[3]: 3 array2[4]: 4 なのですが、実行すると次のように表示されます。 array2[0]: 0 array2[1]: 1 array2[2]: 2 array2[0]: 0 array2[1]: 1 array2[2]: 2 array2[3]: 0 array2[4]: 1 まず最初に、array1という名前のポインタをつくり、malloc関数にて整数3つ分の領域を確保し、整数0、1、2を投入する。次に、array2という名前のポインタをつくり、array1と同じ領域を指すようにする。なので、array2にはデータを投入しなくても参照すると既に0、1、2が入っている。 次に、realloc関数にて領域を2つ追加する。追加された領域には、array1ポインタ経由で実データに整数3、4を投入する。実データが変更されたので、array2ポインタ経由でデータを参照すると、0、1、2、3、4が参照出来る、と思ったのですがそうなっていません。array1ポインタ経由で見ると、きちんと0、1、2、3、4が参照出来るのですが。。 私のreallocの理解に誤りがあれば教えて下さい。宜しくお願いします。

専門家に質問してみよう