1

The questions I'm asking are very basic, but I'm trying to understand the behaviour of pointers in C++ by doing exercises in the compiler. So, for example, I start by declaring an int pointer *p and trying to ascribe it some values and print it:

#include <iostream>
using namespace std;

int *p, i;
int main(){
    i=5;    
    p=&i;
    cout<<*p<<endl;
    return 0;
}

This is very clear and easy, right? But while I'm wondering why the C++ syntax works this way, I test another way of assigning a value to a pointer:

#include <iostream>
using namespace std;

int *p, i;
int main(){
    i=5;    
    p=&i;
    *p=3;
    cout<<*p<<endl;
    return 0;
}

Obviously, the result is different now. The question is, why this wouldn't work:

#include <iostream>
using namespace std;

int *p, i;
int main(){
    *p=3;
    i=5;    
    p=&i;
    cout<<*p<<endl;
    return 0;
}

Why do I have to dereference the pointer first before assigning it a value, but direct assignment would not work without dereferencing?

Also, if in the second example I wrote I added another assignment:

int main(){
    i=5;    
    p=&i;
    *p=3;
    *p=6;
    cout<<*p<<endl;
    return 0;
}

This would not change the value stored at *p (it would still be 3). I don't simply want to learn by memorising this pointer behaviour, I'm interested in understanding why it works this way. Thanks.

  • 1
    Where you are using `*p=3;` when `p` isn't initialized to a valid address, you have a sample for _'undefined behavior'_, no more no less. – πάντα ῥεῖ Jun 21 '14 at 12:46
  • OK, but why does it work (ie, *p gets assigned 3) if I do this after dereferencing p? Is it because this is the standard defined behaviour for assigning a value to a pointer? – user3762829 Jun 21 '14 at 12:50
  • What makes you think _'it works'_?!? Anything could happen, it's undefined. Your fridge may explode ... – πάντα ῥεῖ Jun 21 '14 at 12:52
  • " I'm trying to understand the behaviour of pointers in C++ by doing exercises in the compiler. " - this is a bad idea, because you have no way of knowing whether what you see is defined behaviour or undefined behaviour. Learn by reading a book. K&R 2 is good for learning pointers in C. In C++ pointers should be used sparingly and left for a later stage of learning if you are a beginner. – M.M Jun 21 '14 at 12:56
  • @Matt - Thanks for the suggestion, I don't think I have a choice, since pointers are part of my C++ course (pointers, pointers arythmetic, pointers arrays, etc). Even if it's a beginner course, pointers are used everywhere. There's a lot more stuff which is simply taught "as is" about C++, since they can't explain it in terms of defined behaviours. – user3762829 Jun 21 '14 at 13:04
  • Sounds like a terrible course and a good way to turn new students off the language. Anyway, C++ is not suited to trial-and-error learning; you must learn via a reference that you can trust to have correct code and explanation. (SO posts are pretty good for that but you will get info in bits and pieces rather than a well presented story). – M.M Jun 21 '14 at 13:05

2 Answers2

3
#include <iostream>
using namespace std;

int *p, i;
int main(){
    *p=3;
    i=5;    
    p=&i;
    cout<<*p<<endl;
    return 0;
}

This doesn't work because you are trying to assign a value to the integer that p points to. That's what this line does:

*p = 3;

That means, "store the value 3 at the location which p points at". But p doesn't point at anything, because you didn't assign it to point to anything until two lines later.

p = &i;

That means, "assign the address of i to be the value of p". Or, in other words, "store the address of i in p". p needs to point to something, before you can assign to the thing p points to. Otherwise you have undefined behavior.

On the last section:

int main(){
    i=5;    
    p=&i;
    *p=3;
    *p=6;
    cout<<*p<<endl;
    return 0;
}

You say this: "This would not change the value stored at *p (it would still be 3)." -- I'm not sure why you say that. Yes, it would change the value stored at *p (which is the value of i). It changes it to 6.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • OK, thanks. So a pointer cannot be assigned a literal directly? I thought this is possible. – user3762829 Jun 21 '14 at 12:53
  • @user3762829 you are not "assigning a pointer a literal". You are assigning a literal to *the thing being pointed to*. Which does not exist because you have not made the pointer point anywhere. – M.M Jun 21 '14 at 12:55
  • @user3762829: Pointers store addresses of other objects. Dereferencing a pointer gets you the object it points to (i.e. the object which is stored at the address the pointer holds). But if you haven't given the pointer an address of a valid object, it is undefined behavior to try to dereference it. – Benjamin Lindley Jun 21 '14 at 12:56
  • @user3762829 I think your problem is that you're seeing `*p = whatever` as some kind of magic syntax. It isn't. `*` is an operator like any other. When you do `*somepointer` it gives you the object that is at the address stored in `somepointer`. So `*p = 3;` gets the object at address `p` and stores `3` in it. If `p` doesn't yet store a valid address (because you haven't given it one yet), you get undefined behaviour. – Joseph Mansfield Jun 21 '14 at 13:03
  • @Joseph - Yes, I got it. Basically the pointer needs to point to something to be able to actually store a value. It can't be an address to nowhere storing something. – user3762829 Jun 21 '14 at 13:08
  • 1
    @user3762829: *"Basically the pointer needs to point to something to be able to actually store a value."* -- That's the wrong language. A pointer pointing to something *is* the pointer storing a value. And that value is an address. An int pointer (`int*`), for example, does not store an int value. It stores the address of an int. When you say `*p = 3;`. You are not storing a value in `p`. To store a value in `p` looks like this: `p = &i;`. – Benjamin Lindley Jun 21 '14 at 13:11
1

The question is, why this wouldn't work:

int *p, i;
int main(){
    *p=3;

here you attempt to dereference p and write something, but since p is uninitialized here (it can be 0, for example), you are trying to write to memory that you didn't allocate, thus this is a segmentation fault.

Also, if in the second example I wrote I added another assignment: [...] This would not change the value stored at *p (it would still be 3).

Actually, it would. Why would you think otherwise?

I'm interested in understanding why it works this way.

You're on the right track, just continue reading (e.g. this thread) and experimenting!

Community
  • 1
  • 1
Pavel
  • 7,436
  • 2
  • 29
  • 42