But a itself is not pointing to another region of memory, it IS the region of memory itself. So when the compiler converts it to a pointer, does it save it (like p) somewhere in memory or it's an implicit conversion?
Logically speaking, it's an implicit conversion - there's no requirement that the implementation materialize permanent storage for the pointer.
In terms of implementation, it's up to the compiler. For example, here's a simplistic bit of code that creates an array and prints its address:
#include <stdio.h>
int main( void )
{
int arr[] = { 1, 2, 3 };
printf( "%p", (void *) arr );
return 0;
}
When I use gcc
to compile it for x86-64 on a Red Hat system, I get the following machine code:
GAS LISTING /tmp/ccKF3mdz.s page 1
1 .file "arr.c"
2 .text
3 .section .rodata
4 .LC0:
5 0000 257000 .string "%p"
6 .text
7 .globl main
9 main:
10 .LFB0:
11 .cfi_startproc
12 0000 55 pushq %rbp
13 .cfi_def_cfa_offset 16
14 .cfi_offset 6, -16
15 0001 4889E5 movq %rsp, %rbp
16 .cfi_def_cfa_register 6
17 0004 4883EC10 subq $16, %rsp
18 0008 C745F401 movl $1, -12(%rbp)
18 000000
19 000f C745F802 movl $2, -8(%rbp)
19 000000
20 0016 C745FC03 movl $3, -4(%rbp)
20 000000
21 001d 488D45F4 leaq -12(%rbp), %rax
22 0021 4889C6 movq %rax, %rsi
23 0024 BF000000 movl $.LC0, %edi
23 00
24 0029 B8000000 movl $0, %eax
24 00
25 002e E8000000 call printf
25 00
26 0033 B8000000 movl $0, %eax
26 00
27 0038 C9 leave
28 .cfi_def_cfa 7, 8
29 0039 C3 ret
30 .cfi_endproc
31 .LFE0:
33 .ident "GCC: (GNU) 7.3.1 20180712 (Red Hat 7.3.1-6)"
34 .section .note.GNU-stack,"",@progbits
Line 17 allocates space for the array by subtracting 16 from the stack pointer (yes, there are only 3 elements in the array, which should only require 12 bytes - I'll let someone with more familiarity with the x86_64 architecture explain why, 'cause I'll get it wrong).
Lines 18, 19, and 20 initialize the contents of the array. Note that there's no arr
variable in the machine code - it's all done in terms of an offset from the current frame pointer.
Line 21 is where the conversion occurs - we load the effective address of the first element of the array (which is the address stored in the %rbp
register minus 12) into the %rax
register. That value (along with the address of the format string) then gets passed to printf
. Note that the results of this conversion aren't stored anywhere other than the register, so it will be lost the next time something writes to %rax
- IOW, no permanent storage has been set aside for it the same way storage has been set aside for the array contents.
Again, that's how gcc
in Red Hat running on x86-64 does it. A different compiler on a different architecture will do it differently.