0

When I tried to access the value(which is an address) stored in the address pointed by the pointer variable, a garbage value is returned. I have posted the code and the output below.

Code:

#include<iostream>

using namespace std;

int main(){
    int *a, b=10, *c;
    a = &b;
    c = &b+1;

    cout << "Address of A : " << &a << endl;
    cout << "Value of A : " << a << endl;
    cout << "Value pointed by A : " << *a << endl;
    cout << "Address of B : " << &b << endl;
    cout << "Value of B : " << b << endl;
    cout << "Value of C : " << c << endl;
    cout << "Value pointed by C : " << *c << endl;

    return 0;
}

Output:

Address of A : 0x7fff3e608d20
Value of A : 0x7fff3e608d1c
Value pointed by A : 10
Address of B : 0x7fff3e608d1c
Value of B : 10
Value of C : 0x7fff3e608d20
Value pointed by C : 1046514972

In the above program, the address pointed by c is the address of a yet *c gives garbage value 1046514972 instead of 0x7fff3e608d1c.

I know, I can access the value of A in some other way but my question is why couldn't I access it in this way. Is this an expected behaviour? If yes, can somebody please explain? Thank you.

edge
  • 31
  • 7
  • 5
    How is `&b+1` the same as `a`? Any behavior is expected here. – LogicStuff Aug 22 '16 at 14:05
  • 2
    (and you shouldn't be expecting a hex string (an address) when printing `*c`, a *value*). – LogicStuff Aug 22 '16 at 14:10
  • Most likely `1046514972` is the overflowed result of `0x7fff3e608d1c` – NathanOliver Aug 22 '16 at 14:11
  • @LogicStuff (&b+1) is the address of a. So, doing *(&b+1) should give the value at the address of a, i guess. – edge Aug 22 '16 at 14:11
  • `&b +1` is the address of `b` **incremented by one** so it's different from the address of `b`. You wrote `a = &b` so `a` contains the address of `b`. How the address `&b+1` which is not the address of `b` and is unrelated to `a` could be the address of `a`? Where did you learn that from? – rocambille Aug 22 '16 at 14:17
  • From the output produced by the compiler, it is way clear that the address of a and the value of &b+1 are same. The memory allocated for a and b by the compiler is contiguous, it seems. – edge Aug 22 '16 at 14:25

1 Answers1

2
c = &b+1;
//...
*c

That's undefined behaviour. Forming a pointer to the location after a variable is valid, but performing indirection through it is not1. Even though some object happens to be there, the compiler is free to do whatever it wants.

As to why 1046514972 is printed, that's 0x3e608d1c in hex. It's just the bytes of the 64 bit pointer reinterpreted as a 32 bit integer. You just happen to get something which kind of makes sense, but since this is undefined behaviour, it's semantically garbage.


1 Technically it's the l-to-rvalue conversion which is undefined, but you don't have to worry about that.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • A single element is considered an array of size one for the purposes of pointer arithmetic – NathanOliver Aug 22 '16 at 14:18
  • @NathanOliver Do you have any standards quotes for that? Regardless of whether the pointer arithmetic is valid, it's still undefined behaviour due to the l-to-rvalue conversion on the pointee. – TartanLlama Aug 22 '16 at 14:24
  • 1
    It is [expr.add]/4 in the C++14 standard: For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type. – NathanOliver Aug 22 '16 at 14:29
  • `&b + 1` is valid, but dereferencing the result is not. So, for example, you could write `for (int* ip = &b; ip != &b + 1; ++ip) std::out << *ip << '\n';`. – Pete Becker Aug 22 '16 at 14:31
  • Also see [this](http://eel.is/c++draft/expr.add#footnote-85) from the newest draft. – NathanOliver Aug 22 '16 at 14:31
  • @NathanOliver Thanks! Is that better? – TartanLlama Aug 22 '16 at 14:34
  • @TartanLlama Kinda. I removed the down vote but I fail to see where l-to-rvalue conversion comes in and why it is undefined behavior. citing [1](https://stackoverflow.com/questions/21411102/treating-a-single-object-like-an-array-with-one-element-taking-one-past-end-poi), [2](https://stackoverflow.com/questions/2405555/string-s-s1-legal-ub), [3](https://stackoverflow.com/questions/14505851/is-the-one-past-the-end-pointer-of-a-non-array-type-a-valid-concept-in-c), and [4](http://stackoverflow.com/questions/38441390/iterating-over-a-single-lvalue) – NathanOliver Aug 22 '16 at 14:39
  • @NathanOliver See [here](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232). – TartanLlama Aug 22 '16 at 14:41
  • I still don't see it. There is no l-value to r-value conversion going on here that I can see. The only UB I see is the the use of the value stored in the one past the end pointer. – NathanOliver Aug 22 '16 at 14:49
  • @NathanOliver Using the value *is* the l-to-rvalue conversion. – TartanLlama Aug 22 '16 at 14:51