If you declare a read/write variable at file scope (without using static
) making it "global", then the compiler cannot assume that some other part of the program (another "translation unit") hasn't modified the variable since last time it was used.
If I compile this on ARM gcc (no EABI) with optimization enabled:
#include <stdint.h>
void check_CRC (uint32_t);
uint8_t msg_LengthWithoutCrc = 16;
void func (void)
{
check_CRC(msg_LengthWithoutCrc);
}
Then it creates a variable in the .data
section which gets loaded into a register before the function is called. And it actually allocates a whole 32 bit word chunk (the compiler internally names it ".L4" in this case) which it probably does to guarantee aligned access. Something like this:
.L4:
.word .LANCHOR0
msg_LengthWithoutCrc:
.byte 16
...
ldr r3, .L4
ldrb r0, [r3]
bl check_CRC
Furthermore, since this variable is allocated in .data
it gets pre-initialized from flash upon program start, meaning that the value 16 is also stored somewhere in the flash. See this answer: What resides in the different memory types of a microcontroller?
However, if I change the variable to be static
, const
or just use #define
and don't modify the variable anywhere, the compiler can then assume that the variable has not been modified by another translation unit. It then just puts the number 16 straight into the machine code:
mov r0, #16
bl check_CRC
The same thing also happens if you move the variable inside the function scope:
void func (void)
{
uint8_t msg_LengthWithoutCrc = 16;
check_CRC(msg_LengthWithoutCrc);
}