1

I am reading Stanford's Essential C document (PDF) and on page 20, the following code is stated:

int* p
*p = 13; // NO NO NO p does not point to an int yet
         // this just overwrites a random area in memory

This does not make sense to me.

As I understand it, we allocate space for a pointer to an integer on the first line, so why cannot we point to a value of an integer (e.g., 13) right away on the second line.

Please explain in detail (diagrams are super helpful) what is happening and why this fails.

eb80
  • 4,700
  • 5
  • 25
  • 30

3 Answers3

12
int *p;
*p = 13;

This means:

  • create an unitialised pointer p which could point anywhere.
  • try to store 13 at that location.

Graphically:

+---+                      +---+
| p | --> points to ?????? |   |
+---+                      +---+
                             ^
                             |
  13 goes into here ---------+

Because p is uninitialised, it's undefined behaviour to try store a value using it.

Uninitialised behaviour is rather annoying (one of my more understated assertions).

It may work perfectly. It may seem to work but corrupt something. It may crash your code. It may affect your code in such a way as to make something go wrong three days from now. It may collapse your CPU into a naked singularity, taking you and your family with it.

It may involve the production of nasal demons and/or airborne swine :-)

Bottom line is that you should not do it.


From your question, you seem to think that *p = 13; makes p point to the value 13. That's not the case, especially since the literal 13 is not actually addressable. The code to do that would be something like:

int xyzzy = 13;     // xyzzy IS addressible,
int *p = &xyzzy;    // so make p point at it.

Again, graphically:

                          xyzzy
+---+                     +----+
| p | --> points to xyzzy | 13 |
+---+                     +----+

That would set p to point to the integer xyzzy, which contains 13.

ajay
  • 9,402
  • 8
  • 44
  • 71
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • To add to @paxdiablo answer, you have to claim the memory that is pointed by `p`. – aisbaa Apr 23 '14 at 08:28
  • I would also I like to add -- may be garbage value is not a valid address form -- writing on that address may causes BUS error – Grijesh Chauhan Apr 23 '14 at 08:30
  • `It may collapse your CPU into a naked singularity, taking you and your family with it.` Yet another reason to avoid UB :) – ajay Apr 23 '14 at 08:52
  • @paxdiablo - "From your question, you seem to think that *p = 13; makes p point to the value 13. That's not the case, especially since the literal 13 is not actually addressable." Bingo! – eb80 Apr 28 '14 at 08:29
4

First a little explanation: Local variables are not initialized. If you declare a variable its value will be indeterminate. Using an uninitialized local variable leads to undefined behavior.

Then on to your problem: You say

so why cannot we point to a value of an integer (e.g., 13) right away on the second line.

But that's not what the second line is actually doing. It's assuming that p already is pointing to some valid memory area, and then dereferences the pointer to write the value 13 to that memory area. If the pointer p is a local variable and haven't been initialized to actually point anywhere, it will in reality contain a seemingly random value which will be the address it's pointing to.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1
int* p;

What the above line means is that p is a pointer to integer. But since we have not defined what address p holds in itself, ie we have not really defined where exactly p points to. All we know is that the address that it holds (or will hold in future), will actually be the address of an integer. So for now, p is pointing to anything and we can't be sure of it.

Now when you do

*p = 3;

Since at this time, the address in p is not really specified by us, so it is quite possible that p is pointing to an address that can not be written onto. So the behaviour is pretty much undefined.

What you should do is

int myInt;
int* p;
p = &myInt;
*p = 3;

What the above code does is, it makes p hold the address of variable myInt. And later, write into that address.

What else you can do is that

int* p;
p = (int *)malloc(sizeof(int));

I am not sure if you are familiar with malloc or not (Don't worry, you will be later). But what it does is, it provides p with a chunk of memory ( that is equal to the size of integer ), and now p is pointing to that particular memory block. Now, we don't need to know what exactly was contained in that memory block, but all we need to know is that the memory that has been allocated to us, can be written into without any undefined behaviour.

Cheers

Kraken
  • 23,393
  • 37
  • 102
  • 162