Repository navigation
ex2
In contrast to some languages (e.g., Python) that allow the programmer to code with little concern for how memory is used, C programming affords relatively direct control over how memory is used and accessed. Therefore, if you are coming from a language such as Python, understanding memory usage in C may take some effort.
Memory--often random access memory (RAM) at the hardware level--enables you to store variables and functions. Whenever you declare a variable, the program requests memory for that variable. For example, on my machine the int is 32 bits, so writing int my_variable; will generate a request for 4 bytes (1 byte = 8 bits) of memory at run time.
We can think of memory being laid out as a very large array of ones and zeros, each of which is called a bit. Typically this array is divided into blocks of 8, each of which is called a byte. Associated with each byte is a numerical address. Here is a visualization of memory organization:
address |-byte-|
0 00000000
1 00000000
2 00000000
3 00000000
4 00000000
...
8729315 00000000
8729316 00000000
... 00000000
You won't usually see memory addresses written as decimals, like they are in the above example. Instead, you will see them written in hexadecimal. The prefix "0x" emphasizes that the values are base-16.
address |-byte-|
0x000000000000 00000000
0x000000000001 00000000
... 00000000
0x000000000009 00000000
0x00000000000a 00000000
0x00000000000b 00000000
0x00000000000c 00000000
0x00000000000d 00000000
0x00000000000e 00000000
0x00000000000f 00000000
0x000000000010 00000000
0x000000000011 00000000
...
0x7ffce8f78a2c 00000000
0x7ffce8f78a2d 00000000
0x7ffce8f78a2e 00000000
0x7ffce8f78a2f 00000000
0x7ffce8f78a30 00000000
...
Let's say I declare a char, which is typically 1 byte, and assign a value of 'a', which corresponds to a numerical value of 61: char my_character = 'a';. I can find the memory address of my_character using the & operator:
printf("%p\n", &my_character);
(Note that the %p format specifier is used for printing memory addresses.) When executed, the above code gave me the following output:
0x7ffce8f78a2c
If I were to look at the specified address, I would see something like the following:
address |-byte-|
...
0x7ffce8f78a2b 00110001
0x7ffce8f78a2c 00111101 <- the char I declared; note that 00111101 is 61 in binary.
0x7ffce8f78a2d 00001011 <- "junk" values; this memory is just some unknown part of my program.
0x7ffce8f78a2e 00000000
0x7ffce8f78a2f 00000000
...
Memory in C programs can be divided into two categories: the stack and the heap. Stack memory is allocated when you declare a variable, and it is automatically freed for reuse when the function in which the variable was declared returns. Heap memory is allocated when the programmer specifically asks for a block of raw memory, which can be done using the malloc (memory allocate) command, included in stdlib.h. Whereas stack memory is automatically freed, heap memory must be manually freed using the free command.