0
void func()
{
   int arr[5]={1,2,3,4,5};
   int variable = arr[1];       //variable will be set to 2
}

when this program is executed there will be contiguous memory equivalent of 5 integers is allocated in stack area of virtual address space as shown below for the array of 5 integers.

   +---+
   |   | a[0]
   +---+ 
   |   | a[1]
   +---+
   |   | a[2]
   +---+
   |   | a[3]
   +---+
   |   | a[4]
   +---+

Is there a space somewhere in the virtual address space (in code/data/stack/heap segment) allocated for the array variable arr itself and not the array of 5 integers?

If not allocated, then-

Consider the code snippet - int variable = arr[1]; which will be converted by compiler as *(arr+1) and will be present in code segment of the address space, which is read-only.

How does the arr is evaluated to the starting address of the array arr during every function call func? Since each time the function is invoked the address of the call-stack could change, hence the address for the array arr also changes. So without having separate space for the array variable arr how can this be achieved?

Darshan L
  • 824
  • 8
  • 30
  • 1
    It's allocated on the stack with a known offset. – Eli Korvigo Jan 21 '18 at 07:53
  • 1
    Your diagram shows the memory allocation of `arr` - it is five `int`s contiguously in memory – M.M Jan 21 '18 at 08:48
  • Yes, every time you enter the function, the array can get allocated at a different place in memory (on the stack, but "stack" is considered an implementation detail). What's the problem with that? Why would `*(arr+1)` have to be a constant expression, evaluated at compile time? Why would there be a problem with getting a pointer to a stack location? The standard only tells you that the array ceases to exist after it leaves its scope, and you shouldn't let the pointer go past the scope. But your question seems to incorrectly assume that pointers to things have to be compile-time constants. – vgru Jan 21 '18 at 09:17
  • The handling of allocation for `arr` is no way different from `variable` (if they happen to reside in memory and are not optimized out). Do you think the compiler allocates memory for "the pointer" to `variable` too? So where is this pointer then stored? Does the compiler then allocate memory for the pointer to the pointer... pointers all the way down? – Antti Haapala -- Слава Україні Jan 21 '18 at 12:06
  • @AnttiHaapala: Yes, there will be memory allocated for "the pointer" to variable; which is machine dependent (32 bits on a 32 bit machine). And it is allocated on either stack segment or data segment for a local/global pointer respectively. Yes, of course, there will be a memory allocated for pointer to pointer as well and all the way down. – Darshan L Jan 21 '18 at 12:15
  • 1
    @DarshanL `int arr[5];` declares and defines an array object named `arr` whose size is `5 * sizeof(int)` and whose address is `&arr`, just the same way as `int variable` declares and defines an `int` object named `variable` whose size is `1 * sizeof(int)` and that resides at address `&variable`. The first duplicate target clarifies that the `arr` is not a pointer just as `variable` is not a pointer. And when you realize that `arr` and `variable` behave allocation-wise exactly alike, you'd then find the answers in the second question sufficient. – Antti Haapala -- Слава Україні Jan 21 '18 at 12:22
  • @AnttiHaapala: Thanks for changing my perception of thinking about arrays. You mean to say - `arr` is just a name to refer to the array object just like 'variable' is the name to refer to a int object, right? Furthermore, can you please rephrase the statement after - "The first duplicate target clarifies ...", i am not able to get what you are trying to convey here. – Darshan L Jan 21 '18 at 12:35
  • 1
    There are 2 questions that I've linked here, since you really have 2 questions. The first one [Is an array name a pointer?](https://stackoverflow.com/questions/1641957/is-an-array-name-a-pointer) answers the question ~ is there memory allocated for the array itself (i.e. you mean is it a pointer) => no. Then the second question answers: [how do compilers assign memory addresses to variables?](https://stackoverflow.com/questions/18446171/how-do-compilers-assign-memory-addresses-to-variables) the second part of your questoin. – Antti Haapala -- Слава Україні Jan 21 '18 at 12:40

2 Answers2

1

How does the arr is evaluated to the starting address of the array arr during every function call func?

On a typical implementation on the x86 architecture, arr's location will depend either on the stack pointer (esp) or the frame pointer (ebp), i.e.: it will be defined in terms of one of those pointer registers by applying a fixed offset.

What may be different for each call to func() is the value of those pointer registers, and not how arr is defined in terms of those (i.e.: the fixed offset).

JFMR
  • 23,265
  • 4
  • 52
  • 76
  • Okay. So mean to say the code snippet - `*(arr+1)` is further synthesized to *((_registerPointingToStackFrame_+_offsetToArrayInTheFunc_) + 1), right? So when the instruction is executed, it fetches the starting address of the stackframe from a particular register and add the offset to reach out to the array's starting index without even storing it(the address of the array) explicitly in some memory. – Darshan L Jan 21 '18 at 12:02
  • 1
    @DarshanL What may change between function calls is the value of *registerPointingToStackFrame_*. The *_offsetToArrayInTheFunc* is generated at compile-time and it is fixed. I would suggest you to see the generated code in assembly. – JFMR Jan 21 '18 at 12:09
  • @DarshanL "without even storing it(the address of the array) explicitly in some memory" -> On the x86 arch it doesn't need to (not even to store it in another CPU register), because the arch supports a specific addressing mode for that: "Base plus index plus offset". It is like: `[BaseReg+Offset+IndexReg]` (`Offset` is constant). That way the address of the element of the array to be accessed can be directly encoded in the instruction. – JFMR Jan 21 '18 at 12:22
0

There is a thing called symbol table in compiler construction. The symbol table stores the name arr and an address (which may be an offset based on the process's address space). Then whenever compiler see this arr[1] it generates necessary assembly code to have a MOV or LOAD instruction from the memory address meant by *(arr+1). The arithmetic of +1 is done by the compiler determining the type it points to. And the symbol table is used to keep the memory address information of the variables. (For example:- In case of function the stack frame allocated to it dictates what the address will be for the starting of the contiguous memory which we designate by the name of the arr - that's why it will change too as the memory allotted to a function may vary on each call to it).

user2736738
  • 30,591
  • 5
  • 42
  • 56