To expand on the other two answers:
On most (non-embedded) platforms, when a unit is compiled, the code and data are stored in sections of an object file. The linker combines these sections together when it assembles the final program. In COFF, PE, and ELF object formats, for example, all code is placed in a .text
section. All preinitialized data is stored in the .data
or .bss
section.
Where these segments actually are is really not important. When the program is loaded, the runtime linker (called ld-linux.so
on Linux) will load the entire program to one or more regions of memory and the operating system will map each of the sections to their own memory segments. This assumes the platform has both an MMU and memory segmentation, as on x86. Many modern operating systems also randomize the locations where these sections are loaded, for security. So for each run of the program, a given function may not have the same address.