Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I don't understand pointers

Tags:

c

pointers

What is a pointer? What is dereferencing? If p is a pointer, what is the difference between *p = some_value and p = other_value? What does p = &some_variable mean? What is a NULL pointer? What happens when you dereference a NULL pointer?

like image 717
n. 1.8e9-where's-my-share m. Avatar asked Feb 04 '23 13:02

n. 1.8e9-where's-my-share m.


1 Answers

Get a stack of yellow sticky notes, a pencil, an eraser, and a pen.

Take a sticky note. Divide it with a horizontal line. Write "note #1" on it with a pen in the top part. (This mark is permanent). Write "7" with a pencil in the bottom part. Stick it to the top left corner of your computer screen.

This note represents a memory location that stores the integer value 7. The top part is the address. Each location has its own unique permanent address. The bottom part is the value being stored.

Take another note, divide it in two areas, and similarly write "note #2" and "13" on it. Stick it to your screen next to the first one. This is another memory location that stores an integer value, 13 this time.

Now take another note. In the "address" part of the note write "note #3". In the "value" part of the note write "note #1" (use the pencil!). You have just created a pointer. Stick it next to the first two notes.

Now write down a couple of shorthands on a separate piece of paper:

a    int     #1
b    int     #2
p    int*    #3

This represents a symbol table. a, b and p are *variable names`. In the next column we have their types, and the third column contains their addresses.

Now let's do some C statements.

a = 77;

Look up a in your symbol table. It is #1. Erase the value part of this note and write 77 instead (that's where the eraser comes handy).

b = 2017;

This is completely analogous to the previous one.

a = b;

Look up a and b in your symbol table. They are #1 and #2 respectively. See what note #2 has in its "value" part. Copy that number to the value part of note #1.

*p = 42;

Look up p in your symbol table. That's note #3. Now find the note with the number written in the value part of note #3. That's the operation called dereferencing. It is denoted by the * in the notation above. Erase whatever is in the value part of that note (not the #3, the one #3 is pointing at) and write 42 instead.

*p = b; 

Do this yourself. Here's what you should get:

p = &b;

Again, look up p and b in your symbol table (#3 and #2 respectively). Now take the address part of #2 (that's the operation represented by &, often called, unsurprisingly, the address-of operator) and copy it to the value part of #3 (of course erase what was there beforehand).

*p = 42;

Should be easy by now.

Now create another pointer under #4. File it in your symbol table as q.

q = NULL;

Find q (that's the #4 note) and write note #0 in the value part. Note that there is no note #0. That's a null pointer. It doesn't point to any address.

Caution: the standard doesn't mandate that the null pointer is actually represented is 0. It could have been note #99999999 or note #-1 or whatever, as long as it's distinct from all existing notes

p = q;

Do this yourself. Here's what you should get:

*p = 42;

What should happen? Ostensibly you should take p (that's #3), find out which note it points to, and change that note. But it points to note #0 now, and there's no such note. You have invoked undefined behaviour. The C standard explicitly declines to specify what your program should do. In practice it is likely to crash with a message such as "segmentation fault (core dumped)" or "program <programname> has stopped working".

like image 123
n. 1.8e9-where's-my-share m. Avatar answered Mar 24 '23 00:03

n. 1.8e9-where's-my-share m.