Skip to content
ajd98 edited this page Apr 11, 2018 · 9 revisions

Exercise 2: Memory and Arrays

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.

An introduction to memory

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
           ...

The stack and the heap

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.

Pointers

Clone this wiki locally