Help me understand pointers

I'm trying to understand how pointers work in relation to other data types. For example:

1
2
3
4
5
6
  int x = 5;
  int *p = &x;

  cout<<p<<endl;
  cout<<&x<<endl;
  cout<<*p<<endl;


The output of this would be:

(memory location)
(same memory location)
5

please help me understand why, if I declare *p = &x and then output the value of each one, they are different?
The x is an integer variable. It stores an integer value.
The p is a pointer. Pointer is a variable that stores a memory address as its value.

The value of variable x is 5.
The value of variable p is the address of variable x.

Printing p shows the value that is stored in p: an address.

The operator & in your code returns the address of its operand.
Therefore, &x returns the address of x.
Printing an address shows the address.

The operator * on line 6 dereferences its pointer operand.
Dereferencing a pointer returns the value stored in the memory address that the pointer stores.
The p stores the address of x. The x has value 5.
Dereferencing p returns the 5.
Printing value 5 shows 5.
are you saying your code snip gives something other than N,N,5 as output?


Thank you, keskiverto, that helps a lot.

jonnin, no, my output is like you said. I just wanted to know how *p = &x, but *p has a different value than &x when printed.
this is a syntax thing as already said. Adding to the excellent post above...

address of (& operator in pointer context) produces a pointer. This is what is happening as well when you "pass by reference" it really means "pass by pointer"

there are multiple dereferences: * and []. I personally always use [0] where others use * because I do a lot of math and * is multiply, and no one wants to see z = *p * *d ; There are some others I won't mention right now for objects.

worse, * declares a pointer as well as dereference. This is what you are seeing that is confusing:

int *p ; //declares a pointer
*p = 3; //dereferences a pointer
p[0] = 3; //same as above, and the only way I will write it, for reasons given.




> when you "pass by reference" it really means "pass by pointer"

The language does not have a concept of "pass by pointer"

A pointer may either be passed by value eg . void foo( int* p ) ;
Or it may be passed by reference eg. void bar( int*& p ) ;
That's it.
Last edited on
void foo (object &x)

that &x is a pointer. Its masked a bit with the syntax, but that is what it is doing.
I feel one has to understand that to understand the "reference" terms that are thrown about.

Its a concept, not a language thing, that I was trying to show.





Last edited on
Right. So:

1
2
3
4
5
6
7
8
9
10
11
void foo( const int& p ) ; // p is a pointer! (masked a bit by the syntax)

void bar( int&& p ) { p += 7 ; }  // p is a pointer to pointer!! (masked bit more by the syntax, of course)

int main()
{
     foo(7) ; // pass "by pointer" to literal!

     bar(34) ; // pass "by pointer to pointer" to literal!!
               // at this point the literal 34 holds the value 41!!!
}


At long last, have I understand this profound concept correctly?.

What else is new?
Last edited on
void foo (object &x)

that &x is a pointer. Its masked a bit with the syntax, but that is what it is doing.


In a less interesting way than JLB, I too suggest that this is wrong. In this context, &x is not a pointer.

The fact that on the inside, the compiler might churn out code that uses memory addresses is not relevant. it certainly doesn't have to do it that way, and to think of a reference as a pointer is incorrect in the C++ language.

Last edited on
Part of the confusion about "Pass by reference" comes from the C language, where passing a pointer as a function argument, was given this terminology. Edit: Apparently that is not strictly correct: everything in C is "pass by value". Passing a pointer argument gives the illusion of pass by reference. But this link says that "Pass by reference" is still technically correct:
http://clc-wiki.net/wiki/C_language:Terms:Pass_by_reference
To me, the name of the pointer variable is the alias for the variable.


But C++ has actual references which is a different concept.

It is tempting to think of references as const pointers (they can't be re-seated to point at something else ) , mainly because they behave like pointers, except that one can't have a container of references - there is std::reference_wrapper for that.

Clues about what actually happens with references can be gained by looking std::add_lvalue_reference . I gather this works like the other traits: it uses TMP (Template Meta Programming ). On my system at least, there is a struct which adds the references to the type. TMP is an altogether different concept, but by reading through the type_traits header file, one can see how the various traits are built up. Some code from my system below.
http://en.cppreference.com/w/cpp/types/add_reference

One would hope that when the compiler comes across a reference variable, it does something similar to the traits to make it a reference.

I still find it hard to think about how it would work without there being a pointer in there somewhere :+) I mean it is one thing to have member that says that it is a reference, but it is another to pass or move an object without copying it - which is the main point of passing by reference, indeed of pointers from C.

Maybe because is wrapped up in a bunch of TMP, it is wrong to think of it as being purely a pointer?

type_traits header file
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
  // Reference transformations.

  /// remove_reference
  template<typename _Tp>
    struct remove_reference
    { typedef _Tp   type; };

  template<typename _Tp>
    struct remove_reference<_Tp&>
    { typedef _Tp   type; };

  template<typename _Tp>
    struct remove_reference<_Tp&&>
    { typedef _Tp   type; };

  template<typename _Tp, bool = __is_referenceable<_Tp>::value>
    struct __add_lvalue_reference_helper
    { typedef _Tp   type; };

  template<typename _Tp>
    struct __add_lvalue_reference_helper<_Tp, true>
    { typedef _Tp&   type; };

  /// add_lvalue_reference
  template<typename _Tp>
    struct add_lvalue_reference
    : public __add_lvalue_reference_helper<_Tp>
    { };

  template<typename _Tp, bool = __is_referenceable<_Tp>::value>
    struct __add_rvalue_reference_helper
    { typedef _Tp   type; };

  template<typename _Tp>
    struct __add_rvalue_reference_helper<_Tp, true>
    { typedef _Tp&&   type; };

  /// add_rvalue_reference
  template<typename _Tp>
    struct add_rvalue_reference
    : public __add_rvalue_reference_helper<_Tp>
    { };

#if __cplusplus > 201103L
  /// Alias template for remove_reference
  template<typename _Tp>
    using remove_reference_t = typename remove_reference<_Tp>::type;

  /// Alias template for add_lvalue_reference
  template<typename _Tp>
    using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type;

  /// Alias template for add_rvalue_reference
  template<typename _Tp>
    using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type;
#endif 
Last edited on
Plus there are things (at least one that I can think of off the top of my head) you can do with references that you cannot do with pointers, so if you think of references as pointers you're throwing away that capability.
Well, if we ignore that the life-time of a temporary can be extended by binding a reference (either an rvalue reference or an lvalue reference to const) to it, the C programmer's view of references would be a plausible one (one that a hypothetical C++ implementation could adopt).

Given:
1
2
3
4
5
6
7
struct A { int i ; int j ; };

void foo( A& a )
{
    ++a.i ;
    a.j *= 7 ;
}


Its equivalent in C could be:
1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct A A ;
struct A { int i ; int j ; };

void foo( A* const pa ) // invariant: p != NULL
{
    // assume for simplicity that the there is no #define a already in effect
    #define a (*pa)

    ++a.i ;
    a.j *= 7 ;

    #undef a
}


And the equivalent of this
1
2
3
4
5
int main()
{
    A a { 3, 4 } ;
    foo( a ) ;
}


would be:
1
2
3
4
5
int main()
{
    A a = { 3, 4 } ;
    foo( &a ) ;
}


This is from where the notion: "a reference is a pointer, masked a bit with the syntax" originates.
Topic archived. No new replies allowed.