Arrays and Pointers C++ (Question + Reference)

I wrote some obvious and also tricky stuff that is used for arrays and pointers in c++. Hope this can be a good future reference on the web.

I have some questions that are expressed in the form of comment in my code, and it would be much more helpful if you guys can explain it according to the program #, so I can follow your words more easily.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <iostream>
using namespace std;
int main () {
//-------------Program 1:-----------------

  // Arrays: 
  
  int a [] = {1, 2, 5, 4, 5};
  a[2] = 3;
  for (int i = 0; i < (sizeof(a) / sizeof(int)); i++){
    cout << a[i] << " ";
  }

  output: 1 2 3 4 5 

//-------------Program 2:------------------

  // Pointers:

  int a = 3;
  int *p;
  int *b;
  p = &a;
  b = p;   // Address of pointer a gets pointed to b using p.
  
  cout << p << endl;  // Prints address.
  cout << b << endl;  // Prints the same address.
  cout << *b << endl; // Prints integer 3.

  // But wait ...
  
    int a = 3;
  int *p;
  int *b;
  p = &a;
  *b = *p;   //  Why doesn't the address gets copied to pointer b ? 
  
  cout << p << endl;  // Prints address.
  cout << b << endl;  //  Prints 0, why ? 
  cout << *b << endl; // Prints integer 3.
  

//--------------Program 3:------------------

  // Continue on pointers:

  int *p1 = new int [5];  // Allocating memory from 0 to 4
  int *p2 = new int {5};  //  Storing 5 in the first memory location (i = 0)? 

  cout << *p1 << " and " << *p2;

  // output: 0 and 5

//---------------Program 4:------------------
  // Arrays and pointers using new int.
  int *q = new int[5];   //works.
  int a [] = new int[5];  //  Doesn't work, why? 


//--------------Program 5:-------------------

  // Arrays and pointers:
  int x[] = {5, 10, 15, 20};
  int *y = &x;  //  Why doesn't this work ? 
  cout << *y;

  // But this works ... 


  int x[] = {5, 10, 15, 20};
  int *y = x;  // How ?
  cout << y << endl;  // prints address.
  cout << *y; //  Only prints 5. How can I make this pointer to print all values? 

  //  Why it is not possible to use loop through pointers using for loops? 
  // Ex. 
   for (int i; i < sizeof(X)/sizeof(int); i++){
      cout << *y[i] << " ";
   }

//--------------Program 6:---------------

// Note: it is possible to use delete (pointer's name); to free up the memory

int *p = new int; 
*p = 2; 

delete p; //  Why not delete *p ? 
p = new int; //  Why not *p = new int; like above. 


//----------------Program 7:---------------

int *p = NULL; // Pointer initialized with null.
p = new int[9]; // Request memory

// Delete array pointed to by p (below line)!
delete [] p; //  What is the difference between delete [] p and delete p ? 

//---------------Program 8:-----------------

int a = 5;
int *p = &a;

a = a + 4;
a = *p + 4;
*p = *p + 4;

cout << a << endl;  //  Prints 17, why not 9 ? 
cout << *p << endl; // Prints 17, why not 9 ?

/* It seems the program is remembering 5 + 4 = 9 and then 9 + 4 = 13 and then
13 + 4 = 17  */

}
Last edited on
I've not been through the entire code yet. Just a comment on reading through the code:
30
31
32
33
34
35
36
37
38
39
40
  // But wait ...
  
    int a = 3;
  int *p;
  int *b;
  p = &a;
  *b = *p;   //  Why doesn't the address gets copied to pointer b ? 
  
  cout << p << endl;  // Prints address.
  cout << b << endl;  //  Prints 0, why ? 
  cout << *b << endl; // Prints integer 3. 

This is another variation on the problem previously discussed.
In this case, b is an uninitialised pointer, it contains garbage ... etc. etc.
http://www.cplusplus.com/forum/beginner/206856/


// Why doesn't the address gets copied to pointer b ?

because both pointers b and p are dereferenced using the * operator. The code copies the value pointed to by p, to the memory location pointed to by b.

// Prints 0, why ?

because b is an uninitialised pointer. It contains garbage. You can't depend on it having the value zero, it could be anything at all.

Dereferencing an uninitialised pointer is an error.
Line 48
 
int *p2 = new int {5};  //  Storing 5 in the first memory location (i = 0)?  

is equivalent to
1
2
int *p2 = new int;    // allocate memory for a single integer.
*p2 = 5;  //  Storing 5 in the only memory location   

Before going further, I suggest you set your compiler to produce as many warning and error messages as possible.
If using the g++, then try compiler option -
std=c++11 -Wextra -Wall -pedantic
Then it becomes a matter of reading and understanding the compiler messages, which highlight and briefly describe these problems.

If you don't understand the compiler messages, then paste those messages and ask for help interpreting what it is trying to say.

Just saying "doesn't work" is to lose a lot of the important diagnostic information which the compiler can give.
1
2
// Program 2
*b = *p;   //  Why doesn't the address gets copied to pointer b ?  

You are not copying addresses. You are copying integers that the pointers are pointing to. b has not been initialized to point to anything so the outcome of this program is undefined (which means anything is allowed to happen).


1
2
// Program 3
int *p2 = new int {5};  //  Storing 5 in the first memory location (i = 0)?  

This creates a single int that has the value 5. Note that it's not an array so you should use delete rather than delete[] when freeing the memory.


1
2
// Program 4
int a [] = new int[5];  //  Doesn't work, why? 

This would have been allowed if a was a function parameter so I don't have a good answer. It's inconsistent.


1
2
3
// Program 5
int x[] = {5, 10, 15, 20};
int *y = &x;  //  Why doesn't this work ?  

Because the type of &x is int(*)[4] (pointer to array of 4 int) which is different from the type of y (pointer to int).


1
2
// Program 6
delete p; //  Why not delete *p ? 

That's just how p is defined. You use it on a pointer that points to the object you want to delete.


1
2
// Program 6
p = new int; //  Why not *p = new int; like above.  

You want to modify the value of p (the pointer).
*p would have been used if you wanted to assign a value to the object that p is pointing to.


1
2
// Program 7
delete [] p; //  What is the difference between delete [] p and delete p ? 

delete[] is used for arrays, otherwise delete is used.


1
2
3
4
5
6
7
8
9
10
// Program 8
int a = 5;
int *p = &a;

a = a + 4;
a = *p + 4;
*p = *p + 4;

cout << a << endl;  //  Prints 17, why not 9 ? 
cout << *p << endl; // Prints 17, why not 9 ? 

p points to a so everywhere you see *p you can substitute with a.
All of the three lines are doing the same thing, namely adding 4 to a.
5 + 3*4 = 17
Last edited on
int a [] = new int[5]; // Doesn't work, why?

This is a declaration (because it begins with the type and the name) of an array, but as the initializer (after the =) it has a pointer. Arrays are not pointers, there is no syntax to initialize an array given a pointer.
1
2
// Program 4
int a [] = new int[5];  //  Doesn't work, why?  

This would have been allowed if a was a function parameter so I don't have a good answer. It's inconsistent.
It's inconsistent in a sense, but as far as I can tell the issue comes from C always passing arrays by reference (i.e., as pointers, and with so-called type decay), both to avoid a copy and because it would be difficult to pass arrays with size determined at runtime.

So when you write blah whatever(int[] name) in either C or C++, that's syntactic sugar for blah whatever(int* name). I strongly dislike the use of the "array-parameter" syntax for this reason -- it's a lie.

But otherwise it is consistent with the language --- C++ is statically typed and so even new[] must return a pointer.

The solution is to use std::vector :).
Last edited on
@chevir, thanks for your detailed explanation.

for program 5,
I believe the correct way for derefrencing b would be making

b = p;
and then we you
cout << b << " " << *b;

This gives me first the address and then the value that is stored in that address which the pointer is pointing to.

for line 48, ok I see, it makes sense.

Also it is a good suggestion for extra compiler errors and warnings. My home computer compiler is codeBlocks and is using MingGw, is it using that new feature you recommended automatically ?


Last edited on
@peter87, thank you for explaining according to the programs, and your information is brief and to the point :)


Note that it's not an array so you should use delete rather than delete[] when freeing the memory.


I see, so pointers get delete and arrays get delete [].

1
2
3
// Program 5
int x[] = {5, 10, 15, 20};
int *y = &x;  //  Why doesn't this work ?   

Because the type of &x is int(*)[4] (pointer to array of 4 int) which is different from the type of y (pointer to int).


Question:
So you mean pointer should only point at one integer ? Then is there any way we can point a pointer to the address of an array that holds several integers ?


1
2
// Program 6
p = new int; //  Why not *p = new int; like above.   

You want to modify the value of p (the pointer).
*p would have been used if you wanted to assign a value to the object that p is pointing to.


I don't understand what you mean. Could you clarify the part which you say "you want ot modify the value of p (the pointer)" ?




@Cubbi,

 
int a [] = new int[5]; // Doesn't work, why? 

This is a declaration (because it begins with the type and the name) of an array, but as the initializer (after the =) it has a pointer. Arrays are not pointers, there is no syntax to initialize an array given a pointer.



So you mean that it is not possible to initialize arrays to a new int, but it is possible to point pointers of arrays to new int ?

Kourosh23 wrote:
So you mean that it is not possible to initialize arrays to a new int, but it is possible to point pointers of arrays to new int ?

The expression new int (as well as the expression new int[5]) has type int*, therefore it can be used anywhere a pointer value is acceptable, such as to initialize another pointer of the same type: int* x = new int; (or int* x = new int[5];).
I can't understand what you mean by "pointers of arrays" and "arrays of new int".
Last edited on
Kourosh23 wrote:
So you mean pointer should only point at one integer ? Then is there any way we can point a pointer to the address of an array that holds several integers ?

Normally you would use a pointer to the first element in the array.

Arrays implicitly "decay" to pointers to the first element so you can assign the array to a pointer without doing anything special.
1
2
int x[] = {5, 10, 15, 20};
int *y = x;

But what really happens is this.
 
int *y = &x[0]; // y points to the first element in x 

The syntax for accessing elements by index is the same for both the array and the pointer. This works because y[i] is just a neat way of writing *(y+i).

For example if you use y[2] to access the third element in the array, what happens is that you move the y pointer two steps giving you a pointer to the third element (y+2). Then the dereference operator * is used to read the value of that pointer *(y+2).
----------------------
|  5 | 10 | 15  | 20 |
----------------------
 ^         ^
 |         |
 |         y+2 (points to the third element in the array)
 |
 y (points to the first element in the array)


Kourosh23 wrote:
I don't understand what you mean. Could you clarify the part which you say "you want ot modify the value of p (the pointer)" ?

What I mean is that the pointer p is modified so that it points to a new location.
1
2
p = new int; 
// p now points to the newly created int 

If you instead had written *p = new int; it would have meant that you wanted to set the int that is pointed to by p equal to new int. This wouldn't work for two reasons.

1. *p is an int. new int returns a pointer to the newly created int so the return type is int*. Assigning an int* to an int doesn't make sense and wouldn't compile.

2. p is not pointing to any valid object because you deleted it on the line above so assigning a value to *p wouldn't be a good idea.


I think what confuses you is the * symbol that is used when declaring the pointer.
 
int *p = new int;

Note that this is not using the dereference operator. It's the same symbol but the meaning is different in this context.

You could have written the same thing in two lines as follows:
1
2
int *p;
p = new int;

The * symbol in this context just means that p is a pointer.

You often see people write * closer to the type instead of the variable name.
 
int* p;

The meaning is the same but it more clearly shows that * is part of the type (the type of p is int*), and it look less like a dereference operator.
Last edited on
Topic archived. No new replies allowed.