I declared an array inside for loop and tried printing its base address.
#include<stdio.h>
int main(){
int n=16;
for(int i=1;i<=n;i++){
int a[i];
int b[16];
int c[n];
printf("%p %p %p\n",(void *)a,(void *)b,(void *)c);
}
return 0;
}
The output goes as follow:
0x7fffe6191740 0x7fffe6191770 0x7fffe6191700
0x7fffe6191740 0x7fffe6191770 0x7fffe6191700
0x7fffe6191740 0x7fffe6191770 0x7fffe6191700
0x7fffe6191740 0x7fffe6191770 0x7fffe6191700
0x7fffe6191730 0x7fffe6191770 0x7fffe61916f0
0x7fffe6191730 0x7fffe6191770 0x7fffe61916f0
0x7fffe6191730 0x7fffe6191770 0x7fffe61916f0
0x7fffe6191730 0x7fffe6191770 0x7fffe61916f0
0x7fffe6191720 0x7fffe6191770 0x7fffe61916e0
0x7fffe6191720 0x7fffe6191770 0x7fffe61916e0
0x7fffe6191720 0x7fffe6191770 0x7fffe61916e0
0x7fffe6191720 0x7fffe6191770 0x7fffe61916e0
0x7fffe6191710 0x7fffe6191770 0x7fffe61916d0
0x7fffe6191710 0x7fffe6191770 0x7fffe61916d0
0x7fffe6191710 0x7fffe6191770 0x7fffe61916d0
0x7fffe6191710 0x7fffe6191770 0x7fffe61916d0
Why is the base address of array getting changed every time? Is memory allocated for every iteration. If so then why is the address not changing for 4 iterations?
Please explain the differences among a
, b
and c
in declarations, memory allocations and base addresses.
These arrays have automatic storage duration, and, conceptually, a new instance of each array is created each time the { … }
statement inside the for
loop is executed. Since, in the various iterations, you request different sizes for the array a
, it is entirely reasonable that the C implementation puts it at a different place in memory, to allow room for its elements. Your C implementation appears to be using blocks of 16 bytes as a unit for how much memory it reserves for the array or for how it aligns it. This is likely a consequence of stack management, as the alignment or block size is likely not needed for the array a
itself.
Quite possibly, the allocations of a
, b
and c
are affected by the fact that, in the abstract computer specified by the C standard, the lifetime of b
begins as soon as execution of the block begins, but the lifetimes of a
and c
begin when execution (“control”) reaches the statements that define them. This is because C 2018 6.2.4 says objects with automatic storage duration that do not have variable length begin life upon entry to the associated block (paragraph 6) and such objects that do have variable length begin life at the declaration (paragraph 7). Thus, as the code is written, b
begins life first, then a
, then c
.
This order of allocation affects where c
is put but not where b
is put. Since b
is created first, it is “earlier” on the stack (at a higher address, which means it gets an address not yet affected by a
). Since c
is created later, it is “later” on the stack (at a lower address, which means it gets an address that is affected by how big a
is). This order is not technically required by the C standard, as the C implementation could arrange the locations as it pleases as long as the same results as defined by the C standard are obtained. However, it appears your implementation has followed the C’s abstract computer model faithfully, creating b
first, then a
, then c
.
Additionally, the proper way to print addresses of objects is to use the %p
format specification and to convert the addresses to void *
:
printf("%p %p %p\n", (void *) a, (void *) b, (void *) c);
The size of b
is the same on every iteration of the loop. The compiler locates it once, and it stays put.
Both a
and c
are technically variable length arrays. The size of c
doesn't change, but it appears that it is allocated at a lower address than a
.
Your array a
grows, so to keep the array clear of the array b
, the start address has to be lower on the stack. And, because c
is located below a
on the stack, it moves too as a
grows. The compiler appears to allocate the stack in quanta of 16 bytes. When the array runs into the other variables, its start is moved down the stack by another quantum of 16 bytes.
A clever compiler could spot that c
is a fixed size during the loop and reorder it so it appears above a
in the stack. Then only a
would change address. Your compiler does not appear to be doing that.
The stack layout appears to be:
1st 4 cycles:
b 0x…901d0
a 0x…901a0 gap to b is 0x30
c 0x…90160 gap to a is 0x40
2nd 4 cycles:
b 0x…901d0
a 0x…90190 gap to b is 0x40
c 0x…90150 gap to a is 0x40
3rd 4 cycles:
b 0x…901d0
a 0x…90180 gap to b is 0x50
c 0x…90140 gap to a is 0x40
This behaviour is completely at the discretion of the compiler. I don't have a good explanation of why the gap between a
and b
is so large when a
has 1..4 entries. It could place the variables at different places every time. Technically, the arrays go out of scope when the loop ends; the variables are redefined on each loop cycle. None of them are initialized. Two of them can't be initialized; you cannot provide an initializer for a VLA.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With