L value and r value, stack and heap

I am a high school student learning Java (in a BlueJ environment).

Context

My book, discussing passing by value and passing by reference mechanisms, uses terms, stack and heap, and also states that each unit in memory (also known as a variable) has the name l-value and r-value , where l means "locator "or" location ", and r means 'read'. The name is used to identify the device, the l-value stores the address of the device, and the value r stores the actual value of the device. In the case of primitive data types, it stores the actual value, and in the case of reference data types, it stores the address of the reference data type that refers to or points to it. When a function with parameters is called, the value r of the actual parameters is copied to the r-value of the actual parameter. In the case of primitive data types, the actual value is copied, and in the case of reference data types, the reference address is copied, because of which in the first case the changes in the actual values ​​do not change, and in the latter case, the actual values ​​change.

My questions

Now I decided to learn more about this on the Internet. I found that discussions on the Internet do not fit my book. Here, the l-value and r-value are considered the value on the left and right sides of the destination sign, respectively. I'm confused.

What is the actual value of l-value and r-value, as well as what my book on stack, heap (I want a simple and clear answer) and unit of memory means. I found a lot of questions on this site regarding stack and heap, but could not understand the answers there, since they were very technical, and therefore I do not have so much technical knowledge. I would also like to know where I can find out more about this.

Here are the pages from my tutorial:

enter image description here

enter image description here

enter image description here enter image description here

+5
source share
2 answers
  • When the terms l-value and r-value were first introduced, l and r really meant left and right. That is, the value of l originally meant on the right side of the assignment, and the values ​​of r meant the right side of the assignment. However, they were later revised to indicate “locator” and “read”, respectively, as your book suggests. The reason was that programming languages ​​such as C have many operators (for example, the address of the & operator), where the operand that is displayed on the right-hand side of the operator still has an l-value.
  • stack and heap are areas in memory. The stack is used to store local variables and function calls. A heap is used to store objects . The heap is shared by all threads in your application, while the stack is assigned to each thread.
+5
source

Stack and heap:

Stack

A stack is simply a specific range of memory that every program starts with. Each program has a stack, and when this programming is started, the CPU actually stores a pointer to 1. where is the "top" of the stack. When a function is called, the code (created by the compiler) writes the values ​​(copies of the parameters, as well as the return address of the code that calls the function) to the point in memory that this stack pointer (SP) refers to. He then modifies the SP to indicate a little further, to the point after the parameters.

When your function returns, it writes the return value to the point in memory that SP points to, and then translates the code execution back into the code that calls this function. This code then copies the return value from the SP location and reduces the SP.

This area is called the stack because the program copies values ​​to it when: 1. you declare local variables or 2. you call functions with parameters.
And then it pushes the parameters and local variables when returning from the function.

(This is how it works in theory. In practice, the compiler instead writes instructions for copying the values ​​to the CPU registers instead, as well as the return value).

heap

The heap simply refers to all other memory that is allocated by the program, usually with a system call (brk on linux) (called malloc in C). A program can have many blocks of memory that it asked the operating system to allocate for it. These pieces of memory (in general) are called heaps.

In java:

  • when you use the 'new' keyword, what it does returns a pointer to some memory that it asked the operating system to give.

  • when you declare a variable not using the new one, what the compiled code will do is simply use the existing memory at the top of the stack's memory area, and then change the stack pointer.

When you use a pointer variable and assign it an object created using new ExampleObject (), you are actually doing both things. In this case, a pointer (reference) will be created at the location of the stack pointer. Then the stack pointer moves (it is added to 8 bytes, the size of the pointer value), then the new () function will receive a new memory link from the heap area, and then the value of this link will be copied to the local pointer variable.

In practice, a language such as Java, when it runs the program, starts with a specific stack of a certain size and a certain amount of memory (called heap) already allocated to it by the operating system, and will request more memory when it runs through space

It would be useful to see how processors work, in particular, how they have registers in which values ​​are stored, and one of them is a stack pointer. Just like they do additions and subtractions. This is important because they do not (usually), for example, when adding, add the number from the reference address in memory to the number at another reference address. If you look at Assembly instructions (similar to java bytecode), what do they do more often:

For example, the function int addnum (int a, int b) {return a + b;} a. Load the number from the SP, that is, where the SP indicates, into register 1

b. Load the number from when the SP points (SP-1) to register 2

with. Call Add a CPU command that stores the result in register R3 d. Copy the value of R3 to SP + 1

What might look like

The code call is as follows: (note that these are compiled examples of CPU instructions - they are different for each processor, and Java has its own bytecode, which is similar. I just use, for example, STORESP => write to stack, LOADSP => loading from stack pointer)

 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 

Then the function itself

 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 

Then the calling function again: Saves the result to x (copy of SP-2) (up to SP-3)

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

Now the function call is completed. So throw away the space allocated on the stack for a and b and the return value (Decreasing SP by 3)

 ADDSP -3 

And now the result is in 'x'

Of course, this is much simplified and inaccurate, but this is just an example to help understand.

But if you can see how these low-level things work, just do something basic, for example, add two numbers, then this will help you understand the "where" and "how" parameters in the functions, and exactly how important the concept of the stack is

Good luck.

+1
source

Source: https://habr.com/ru/post/1264303/


All Articles