A global variable is no different to any other variable... The difference being it can be accessed from any function within the scope of the file it resides in... Local variables are disposable ( unless declared "Static" )
When you declare a Global variable it is placed in UDATA which is usually in the GPR section ( after the access ram )
If declared as IDATA it is placed after the UDATA in the same DATABANKS..
The HEAP memory... Is dynamically assigned at runtime....
I'm not sure what compiler or device you are using, but the avr-libc documentation is excellent. https://www.nongnu.org/avr-libc/user-manual/malloc.html
I think the general info there is valid for all C compilers. PIC memory is different from avr, but I think the compilers do their best to handle it.
.data segment:
variables that are defined outside all functions (i.e. global) and initialized, are stored at .data segment.
also static variables that are initialized are stored at .data segment.
.bss segment:
variables that are defined outside all functions (i.e. global) and NOT initialized, are stored at .bss segment.
also static variables that are NOT initialized are stored at .data segment.
When are they stored in the .data / .bss segments?
When the board powers-up, before the program begins?
Are you working on a PC or a micro.... It very much depends on which platform you are working on...
AVR and PIC do not comply with the data segment rules of the household PC....
The humble PIC has very small data segments compared to the PC... The PC has 64k data segments as opposed to 255 bytes on the pic18's.. The pic compilers have UDATA (.bss) and IDATA (,data)..
There is no HEAP to speak of, hence not much use for alloc / malloc routines... The larger PIC32 and LPC ( ARM) are much better equipped for these routines...
Only constants are defined at code time... All variables are defined at runtime... Whether they are .data or .bss depends on their initialization.... If ALL variables are declared as uninitialized then all the space available will be used for .bss ( UDATA.... However it depends on the compiler....
If you work on the C18 compiler, there is a linker script available to you so you can alter DATABANKS at runtime..
Global and static variables are assigned a memory location at linker time. The linker handles the tracking of every variable, so that they are handled correctly throughout the code.
Also, there is an initialization code before the main program is entered. This is where correct initialized values are loaded from flash memory to the correct ram-location.
A variable declaration means two things... If they are UDATA, A place is earmarked for them,,, They are not used until you actually read or write the location that has been reserved...
Or if the are IDATA, then they are assigned the value as the declaration occurs.... It HAS to be at runtime as the location isn't there until the chip is running..
Probably if they are global... Sometimes libraries such as the math library declare oodles of bytes for their purpose... They are kinda global but in the scope of that library only...
Global and static variables are assigned a memory location at linker time. The linker handles the tracking of every variable, so that they are handled correctly throughout the code.
Also, there is an initialization code before the main program is entered. This is where correct initialized values are loaded from flash memory to the correct ram-location.
Yes. There are differences between compilers etc, but that is the general idea. There can be all kinds of initializations (stack, interrupt vectors) before the code enters the Main-function itself. If your tools allow you to look at the generated assembler code (disassembly) you can write simple example applications yourself and look what is really happening there.