2017-02-16 8 views
5

私はJavaを学ぶ高校生です(BlueJ環境で)。l値とr値、スタックとヒープ

コンテキスト

マイブック、値によってパスを検討しながら基準機構を通過、用語を使用し、スタックとヒープとも(また、変数としても知られる)メモリの各ユニットは、を有していることを述べてL値r値に名前を付けここで「ロケータ」または「位置」と「読み取り」を意味Rを表しL。名前はユニットを識別するために使用され、l値はユニットのアドレスを格納し、r値はユニットの実際の値を格納します。プリミティブデータ型の場合は実際の値を格納し、参照データ型の場合はそれを参照または参照する参照データ型のアドレスを格納します。パラメータを持つ関数が呼び出されると、実際のパラメータのr値が実際のパラメータのr値にコピーされます。プリミティブデータ型の場合は実際の値がコピーされますが、参照データ型の場合は参照アドレスがコピーされますが、前者の場合は実際の値に変更はなく、後者の場合は実際の値に変更があります。

私の質問

今、私はインターネット上でこのことについての詳細を学ぶことにしました。私はインターネット上の議論が私の本に合っていないことを知りました。そこでは、l値とr値はそれぞれ割り当て記号の左辺と右辺の値と呼ばれます。私は混乱しています。

実際のl-valueとr-valueの意味は何ですか?また、スタック、ヒープ(単純でわかりやすい答えが欲しい)とメモリ単位の意味は何ですか?私はスタックとヒープを扱うこのサイトで多くの質問を見つけましたが、彼らは非常に技術的なので、答えを理解できませんでした。そのような技術的な知識はあまりありません。

enter image description here

enter image description here

enter image description here enter image description here

+0

「インターネット上の議論」からのリンクやエキサイトを提供できますか? – CKing

+2

Javaには実際には左辺値と右辺値の概念はありません。言語仕様におけるそれらの唯一の言及は、[ここ](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html)です。ここでは、「変数(§4.12 )(Cでは、これは左辺値と呼ばれます)。右辺値は基本的に単なる変数ではなく、値を代入することはできません(代入の「右辺」)。 –

+0

[Wikipedia](https://en.wikipedia.org/wiki/Value_(computer_science)#lrvalue)の記事が参考になるかもしれません。スタックとヒープについては、残念ながら技術的な説明なしに説明することはできません。少なくともそれは変数との関係を説明するものではない。 – RealSkeptic

答えて

5
  1. :また、私はここに、この

    についての詳細を学ぶことができる場所を知っている私の教科書からのページがあるしたいと思います用語l-valueおよびr-valueを最初に作成し、 lとr は実際には左右を意味します。すなわち、l値はもともとは左に の代入とr値の左側を意味し、 割り当ての右辺を意味していました。しかし、後で、あなたの本が示唆しているとおり、それぞれ 「ロケータ」と「読む」と表示されるように改訂されました。理由は であり、Cのようなプログラミング言語では多くの演算子(例えば、 演算子のアドレス&)があり、演算子の右辺 の右側に現れる演算子はl値です。

  2. stackおよびheapは、メモリ内の領域である。スタックは、 ローカル変数と関数呼び出しを格納するために使用されます。ヒープは、objectsを格納するために使用されます。 スタックが が各スレッドに割り当てられている間、ヒープはアプリケーションのすべてのスレッドによって共有されます。
+0

ヒープにすべての参照データ型が格納され、スタックにすべてのプリミティブデータ型が格納されているとしましょうか? – MrAP

+0

@MapAP No.プリミティブメンバーを含むオブジェクトを考えてみましょう。 – EJP

+0

@MrAP EJPは、プリミティブがインスタンス変数として宣言されていると、ヒープにあるラッピングオブジェクトが格納されている場所に格納されることは明らかです。しかし、プリミティブがメソッド本体で宣言されていれば、スタックにスタックされます。 – VHS

1

スタックとヒープ:

スタック

スタックは、単に各プログラムが始まるメモリの特定の範囲です。すべてのプログラムにはスタックがあり、そのプログラミングが実行されているとき、CPUは実際にスタックの「トップ」があるところへのポインタを格納します。 関数が呼び出されると、コード(コンパイラによって生成される)は、このスタックポインタ(SP)によって参照されるメモリ内のポイントに値(パラメータのコピー、および関数を呼び出したコードの戻りアドレス) 。次に、SPを修正して、パラメータの後のポイントまでさらにビットをポイントします。

戻り値は、SPが指すメモリ内のポイントに戻り値を書き込んだ後、関数を呼び出したコードにコードの実行を戻します。その後、そのコードはSPの場所から戻り値をコピーし、SPをデクリメントします。

この領域はスタックと呼ばれます。これは、1.ローカル変数を宣言したとき、または2.パラメータを使用して関数を呼び出すときに、値をコピーするためです。
そして、関数から返ってくるときには、パラメータとローカル変数がオフになります。

(実際にはコンパイラは実際には値をCPUレジスタにコピーし、戻り値もCPUレジスタにコピーするように指示します)。

ヒープ

ヒープは、単に通常(Cでのmallocによって呼び出される)システムコール(LinuxでBRK)によって、プログラムによって割り当てられ、他のすべてのメモリを指します。プログラムには、オペレーティングシステムに割り当てようとしているメモリのチャンクがたくさんある可能性があります。これらのメモリチャンク(全体として)は、ヒープと呼ばれます。 Javaで

:あなたは「新しい」キーワードを使用する場合

  • 、何それがないことはあなたにそれを与えるために、オペレーティング・システムを尋ねたいくつかのメモリへのポインタを返しています。

  • 新しい変数を使用しない変数を宣言すると、コンパイルされたコードはスタックメモリ領域の上部にある既存のメモリを使用してスタックポインタを変更するだけです。

ポインタ変数を使用して、新しいExampleObject()で作成するオブジェクトを割り当てると、実際には両方が実行されます。この場合、ポインタ(参照)変数はスタックポインタの位置に作成されます。次に、スタックポインタが移動され(ポインタ値のサイズである8バイトで追加されます)、new()関数はヒープ領域から新しいメモリ参照を取得し、その参照の値がローカルにコピーされますポインタ変数。

実際には、プログラムを実行しているときにJavaのような言語は、特定のサイズのスタックと、オペレーティングシステムによってすでに割り当てられている特定のサイズのメモリ(ヒープと呼ばれます)から始まり、スペースが不足しています

CPUがどのように機能しているか、特にそれらが値を格納するレジスタをどのように持っているか、そのうちの1つがスタックポインタです。どのように加算と減算を行うか。これは重要です。なぜなら、たとえば追加時に、参照されたアドレスから別の参照先の番号に数値を追加するなどしないためです。アセンブリ命令(Javaバイトコードに似ています)を見ると、より頻繁に何が行われるのでしょうか?

たとえば、次のような関数があります:addnum(int a、int b){return a + b;} a。 SPが指しているSP ieから番号1をレジスタ1にロードします。

b。 SPが指している直前の番号(SP-1)をレジスタ2にロードします。

c。呼び出しAdd CPU命令。結果はレジスタR3に格納されます。 d。 SPにR3の値をコピー+ 1

このような

電話番号のように見えるかもしれません

:(ノートでは、これらは、例えば、CPU命令を作っている - 彼らは、各CPUに対して異なっており、Javaがあり、独自のバイトコードを持っています類似している。私はその後)

int x; 
x = addnum(9,6); 

INCSP +1 #allocate x at location SP and increment SP by 1 

# start function call 
# make 3 spaces, for a, b, and b and return value 
INCSP +3  #add 3 to SP register 
STORESP 9,0   # copy 9 value to SP-0 
STORESP 6,-1   # copy 6 value to SP-1 

JUMP addnum # jump to executing the function code     

をスタックポインタから例えばSTORESP =>積層する書き込み、LOADSP =>負荷を使用している、機能自体は

LOADSP,0,R1  #copy from SP-0 (a) into reg 1 
LOADSP,-1,R2  #copy from SP-1(b) into reg 2 
ADDREG,R1,R2,R3 # add reg1 reg2 and store in R3 

STORESP,R3,-2  #save the result to SP-2 
RETURN 

そして再び関数を呼び出します。x(コピーSP-2)で 店舗結果(SP-3)

LOADSP,-2,R1 
STORESP,R1,-3 

は今、関数呼び出しが行われます。だから、

ADDSP -3 

そして今結果(3のSPをデクリメントすることにより)aとbのスタックおよび戻り値 に割り当てられたスペースを捨て、これはもちろん「x」の

でありますはるかに単純化されていて正確ではありませんが、理解を深めるための例のためだけです。

しかし、これらの低レベルのものがどのように機能するかを見れば、2つの数値を追加するような基本的なことを行うだけで、関数のどこで「どのように」パラメータが渡されるのか、重要なスタックコンセプトは

幸運

関連する問題