C/Pointers with words

From Attie's Wiki
Revision as of 14:48, 13 March 2012 by Attie (Talk | contribs)

Jump to: navigation, search

Having been criticized by my colleagues, I decided to add some words to my Pointers page.

A Variable

Before we begin, this page assumes an x86 system (32-bit) - which means that addresses and integers are 32-bit / 4 bytes.

If we start by thinking about a normal variable, i, of type int.

An int is just a block of 4 bytes that the compiler promises it will find memory for.
In reality this comes from the stack, but that is a detail for another time.

Let's declare i and assign 0xDEADBEEF to it.

int i;
 
i = 0xDEADBEEF;

If you were to inspect the memory for this process, and represent it visually, we might find the following (the colouring will become apparent later).

Address Value Note
...
0xBF893E8F 0xDE i MSB
0xBF893E8E 0xAD i
0xBF893E8D 0xBE i
0xBF893E8C 0xEF i LSB
...

From this memory map, we can see that the variable i is stored at address 0xBF893E8C, and because the memory is byte addressable, i uses 4 'slots' - 0xDE, 0xAD, 0xBE, 0xEF.

A Pointer

Now let's consider a pointer.
They are just like normal variables, but they have a special meaning to the compiler.

int *p;
 
p = 0xDEADBEEF;

The code above gives exactly the same result, and assuming that p is located at the sample place in memory that i was, the previous memory map is still valid.

But when we come to 'de-reference' p we are going to have a problem.
The term 'de-referencing' is the act of following a pointer, to access the variable to which it points. This can be done in two ways:

*p     /* this is usually used in a situation similar to this, when 'p' points at a single variable */
p[0]   /* this is usually used when 'p' points to an array of variables */

The map below shows the value of p as well as the memory that it points to.
As you can see, this is no longer a simple variable, because its value is used to locate some other memory.
In this case, the memory at 0xDEADBEEF is not allocated to anything, and accessing it will cause a segfault (your program will crash).

Address Value Valid? Note
...
0xDEADBEF2 ?? No ?
0xDEADBEF1 ?? No ?
0xDEADBEF0 ?? No ?
0xDEADBEEF ?? No ?
...
0xBF893E8F 0xDE Yes p MSB
0xBF893E8E 0xAD Yes p
0xBF893E8D 0xBE Yes p
0xBF893E8C 0xEF Yes p LSB
...

Let's make something useful, instead of something that will crash.
Consider the following code:

int i;            /* our variable */
int *p;           /* our pointer */
 
p = &i;           /* assign the address of 'i' to 'p' */
 
*p = 0x12345678;  /* effectively assigns 0x12345678 to 'i' */

In this snippet, we make p point at i, and then store 0x12345678 in the memory that p points to.
This effectively stores 0x12345678 in i, and could result in the following memory map.

Address Value Valid? Note
...
0xBF893E8F 0x12 Yes i MSB
0xBF893E8E 0x34 Yes i
0xBF893E8D 0x56 Yes i
0xBF893E8C 0x78 Yes i LSB
0xBF893E8B 0xBF Yes p MSB
0xBF893E8B 0x89 Yes p
0xBF893E8B 0x3E Yes p
0xBF893E8B 0x8C Yes p LSB
...
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox