> I think it is a challenge for a compiler to know where the variable is declared.
Not really.
At the start of the .c file, the scope is global.
After that, it's just a matter of keeping track of how many open and close braces it sees.
Code:
/* Starts in global scope */
int global;
void foo ( void )
{ /* now a local scope begins */
}
/* back to a global scope */
Example, using objdump to display detailed information about each symbol.
Code:
$ cat foo.c
#include <stdio.h>
extern int other;
int gvar = 2;
static int lvar = 22;
int main ( ) {
int temp = 42;
printf("%d %d %d %d\n", other, gvar, lvar, temp);
}
$ gcc -c foo.c
$ objdump -t foo.o
foo.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 foo.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000004 l O .data 0000000000000004 lvar
0000000000000000 l d .rodata 0000000000000000 .rodata
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .note.gnu.property 0000000000000000 .note.gnu.property
0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 g O .data 0000000000000004 gvar
0000000000000000 g F .text 0000000000000045 main
0000000000000000 *UND* 0000000000000000 other
0000000000000000 *UND* 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000 *UND* 0000000000000000 printf