I don't understand pointers, templates, polymorphism......

Pages: 123
closed account (E3vDSL3A)
Well all of your hard written examples have been helpful, AND appreciated much, but I still can't use pointers though.

Like I can get the basic: they point. But how do I know exactly what to point to and what pointing to any thing will do? You said some thing(Moschops)about how you can find a picture by pixels, I don't know.

But I don't get that. How do I know where to point with the pointer? How do I know that where I'm pointing to exists, why what I'm pointing to is doing some thing or whether or not using a different type of pointer or just pointing....Uh.....Sorry, but even with all of that effort it still comes as quite confusing to me.

I can't understand the memory accessing, pointing, very little.....But since it's some thing needed I want to understand it more but tutorials are of no help and books are the same.

WHY EXACTLY WOULD I NEED THEM?

PS: God, these pointers are starting to sicken me.
Last edited on
Let's imagine you need a function that for whatever reason needs to return 2 results. You can't do this with a 'normal' function - ie. it can only return one value. With pointers, you can do this (sort of).

Consider this example:
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
#include <iostream>

void swap_with_pointers(int*, int*);
void swap_without_pointers(int, int);

int main(int argc, const char* argv[])
{
  int x = 1;
  int y = 5;

  std::cout << "Before swapping..." << std::endl;
  std::cout << "x = " << x << std::endl;
  std::cout << "y = " << y << std::endl << std::endl;
  
  // first, let's try to swap without using pointers
  swap_without_pointers(x, y);

  std::cout << "After call to swap_without_pointers..." << std::endl;
  std::cout << "x = " << x << std::endl;
  std::cout << "y = " << y << std::endl << std::endl;

  // now let's try the other function using pointers
  swap_with_pointers(&x, &y);

  std::cout << "After call to swap_with_pointers..." << std::endl;
  std::cout << "x = " << x << std::endl;
  std::cout << "y = " << y << std::endl << std::endl;

  return 0;

}

void swap_with_pointers(int *x, int *y)
{
  int temp = *x;
  *x = *y;
  *y = temp;
}

void swap_without_pointers(int x, int y)
{
  int temp = x;
  x = y;
  y = temp;
}


Here is the output from this program:

Before swapping...
x = 1
y = 5

After call to swap_without_pointers...
x = 1
y = 5

After call to swap_with_pointers...
x = 5
y = 1


So, what happened here? As you can see, the 'swap_without_pointers' function, at first glance, looks like it SHOULD swap the values of the two variables, but as you can see in the output, it does not. The reason is when you declare a function like this: void swap(int, int); you are telling the compiler that you will be passing two int's to this function by value. This means that when the function is called, the function actually uses a copy of the parameters. When declaring the function like this: void swap(int*, int*); we tell the compiler that we will give the function the memory addresses of two int variables. Thus, we can actually change the values of the passed variables within the function.

Does this make any sense? If not, ask specific questions. If you haven't actually compiled and tried all my examples, I would suggest doing that to try for yourself what we are all talking about. You can literally copy and paste the entire code into your editor/IDE, or whatever you use to compile and run code.
closed account (E3vDSL3A)
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
#include <iostream>

void swap_with_pointers(int*, int*);
void swap_without_pointers(int, int);

int main(int argc, const char* argv[])
{
  int x = 1;
  int y = 5;

  std::cout << "Before swapping..." << std::endl;
  std::cout << "x = " << x << std::endl;
  std::cout << "y = " << y << std::endl << std::endl;
  
  // first, let's try to swap without using pointers
  swap_without_pointers(x, y);

  std::cout << "After call to swap_without_pointers..." << std::endl;
  std::cout << "x = " << x << std::endl;
  std::cout << "y = " << y << std::endl << std::endl;

  // now let's try the other function using pointers
  swap_with_pointers(&x, &y);

  std::cout << "After call to swap_with_pointers..." << std::endl;
  std::cout << "x = " << x << std::endl;
  std::cout << "y = " << y << std::endl << std::endl;

  return 0;

}

void swap_with_pointers(int *x, int *y)
{
  int temp = *x;
  *x = *y;
  *y = temp;
}

void swap_without_pointers(int x, int y)
{
  int temp = x;
  x = y;
  y = temp;
}


I'm sorry, but that's too hard to understand. Could you give a simpler example showing a real use of pointers? Like why do they need to be used in Windows API programming?
@Moschops: Wow, that is the best explanation of pointers I've ever seen. Honestly, I didn't get them either until I saw this thread. I'm definatly bookmarking this.
WHY EXACTLY WOULD I NEED THEM?


My first usage of pointers came when I needed to pass a 2dimensional array to a function
and change the data.

Pointers (and references) make that process IMO easier and less costly memory wise.

ie:void test(string* var)
var is a pointer, so in the function I can change its data without making copies.
void test(string& var) is essentially the same.
Q: Okay what are pointers, and why do we need them?
A: Pointers are the same as variables but instead of directly working with the variable, you are working with memory addresses.

Every variable in an executing program is given a section of memory large enough to hold a value of that variable's type. Each byte (or unit) of memory is given a unique address. The address given to any variable is the first byte of its allocation.

So if I allocate 4 units of memory, the address is the first byte in the sequence. So if I create an int variable called "myint", my compiler reserves 4 bytes of memory in a spot, then gives the address to the variable "myint". By saying &myint, I can receive and see the address. A value that represents the address of a memory location, or holds the address of a variable is called a pointer.

Now like any data type, memory address can be stored in what we call a pointer variable, or just simply a pointer. Every time you create a pointer variable it needs to know what type of memory its pointing to. (This is important for many things explained later on.) So if you want a pointer to hold the address of an int you must declare the variable as the type "int *variablename". The * (known as an asterisk) indicates that variablename is a pointer to an integer.

Q: Now why do we need pointers?
A: Pointers are really the underbelly of many functions in C and C++ and without them certain data would no longer be available. The main one is arrays. Arrays are the very heart are pointers. When you declare an array:

int array[10];
You are actually creating a constant pointer to the first element of the array.
Run this in C++:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

using namespace std;

int main()
{
  int array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  
  cout << array << endl; // This should print out some Hex number (starting with 0x)
  
  return 0;
}


Note that cout << array; prints some random looking garbage. That is an address, and that means array[] is a pointer variable. But what is the point? Well arrays don't function without an important things from pointers: Dereferencing and Pointer-arithmetic.

Note how we access an item from an array. We usually call array[index]. What is that actually doing? Its a simplified syntax for pointers. What [] actually does in this case is that it does math on the pointer, incrementing its size by the index (like say 1) and the number of bytes that array is declared (in my case, its an int array, and my compiler says its 4 byte large). So first [] takes the pointer address which for now lets just say the address of my pointer is 20. So beyond 20 there's address 24, 28, 32, 36, and 40 which are the front most byte of the integers in my array. Now when I call array[1] I actually tell the compiler to do this.:

Take the address stored at array (in this case 20), and add 1 multiplied by the size of integers which is 4. Then tell me what value stored there. This in arithmetic looks like
20+1*4 = 24
, the address of the first integer memory location after 20! Now [] just translate the bits of data there and represents it as an int.

Q: But when will I need pointers?
A: In the long run, you'll need them when working with dynamic memory otherwise known as the HEAP. Programs are only allowed to use the HEAP through address, and pointers are the holders of addresses of memory. You see that funny relation?

Q: Do I need a pointer to work with arrays?
A: No. The [] does it for you.

Q: What if I want make the array larger or smaller?
A: You can't without pointers and working in the HEAP. This is very risky and error prone. When working the the HEAP you are required to clean up your own messes. Failure to do so causes problems. And thats not good. There is no janitor, custodian, or garbage man to clean these messes. Only the programmer. If you fail to clean up too much you will run out of memory and eventually the computer your working on will crash?

There is a substitute. Vectors. Vectors are dynamic sizing arrays. They grow and shrink as you need and they play in the HEAP. When your done with them, like when your program ends, they know how to clean up after themselves before they leave. They are nice an tidy!

You'll find that vectors also have many advantages over arrays.
1. Vectors are better at handling your own datatypes when you create structures and classes.
2. Vectors are smart. So smart they remember their size for you. No longer do you need to remember you only have 5 spaces in those old arrays.
3. Vectors can be really big and grow for the ocassion! Now if you read in data you no longer have to limit to 10 items. You also never need to make more space than you need.
If you used an array and wanted to nable users to imput as much as they wanted into it, the code would be very long, and you'd need to work in the HEAP. By using Vectors, lose that fear of error programs!

Q: So do I need pointers? Will I ever use them?
A: Yes. But if you don't understand them you shouldn't fear or panic. They are a complicated item, but once you begin using them crrectly you'll ask how you ever got by without them before!
Last edited on
When you declare an array:
int array[10];
You are actually creating a constant pointer to the first element of the array.

No. Arrays are not pointers, they just decay into pointers under certain circumstances. This is most visible when you have a multidimensional array. int a[2][2]={{1,2},{3,4}}; This is an array of 2 arrays each of 2 integers. a[0] and a[1] are arrays of 2 integers. Consider, however, that the following things are true:
1
2
3
4
a==a[0];
a==*a;
a[0]==*a;
**a==a[0][0];

That is, *a and a[0] do not actually dereference a pointer. They do nothing at all, except semantically *a and a[0] are int[2], not int[2][2]. On the last line, if a was truly a pointer, **a would access whatever is at the address 1. It doesn't. Arrays are not constant pointers to their elements.
Arrays are much more complicated than pointers!
Last edited on
Good job. You confused even me.

EDIT: (stupid tab+enter key) God forbid we go into double pointers.

Your right by the way. I just tried to give the easiest metaphor I could think of. The inner workings of everything are pretty deep, and I get what you're saying.

I personally try not to think of 2 dimensional arrays, and actually avoid using them in code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

using std::cout;
using std::endl;
using std::cin;

int main()
{
  int array[2][2];

  array[0][0] = 1;
  array[0][1] = 2;
  array[1][0] = 3;
  array[1][1] = 4;

  cout << *(*(array)+3) << endl;


  return 0;
}


Eventually, as you said they decay into pointers, but are more complex. I prefer separating arrays from pointers as I really only define pointers (personally) as containers for malloc() or new items.
Last edited on
Uhh.. Ok, well, I'll try to explain better later, ok? Maybe put it in the Articles section. There doesn't seem to be a whole lot of info on C/C++ arrays anywhere on the internet.
rocketboy can you do something with arrays and structures that explains double indirection with 2 pointers. i dont know if they are both pointers or 1 pointer and 1 dereference operator. code that looks like this test**.
Last edited on
closed account (iw0XoG1T)
@rocketboy

Consider, however, that the following things are true:
1
2
3
4
a==a[0];
a==*a;
a[0]==*a;
**a==a[0][0];



1
2
3
4
5
6
7
8
9
10
#include<iostream>
int main()
{
   int a[2][2]={{1,2},{3,4}};
   if(a==a[0])std::cout<<"true\n";
   if(a==*a)std::cout<<"true\n";
   if(a[0]==*a)std::cout<<"true\n";
   if(**a==a[0][0])std::cout<<"true\n"; 
   return 0;
}

temp.cpp: In function ‘int main()’:
temp.cpp:5: error: comparison between distinct pointer types ‘int (*)[2]’ and ‘int*’ lacks a cast
temp.cpp:6: error: comparison between distinct pointer types ‘int (*)[2]’ and ‘int*’ lacks a cast
Last edited on
What I meant was that the VALUES are exactly the same. The types are different as I already pointed out.
1
2
3
4
5
6
7
8
9
10
#include "stdio.h"
int main(){
	int a[2][2]={{1,2},{3,4}};
	printf("%d\n",a);
	printf("%d\n",a[0]);
	printf("%d\n",a[0][0]);
	printf("%d\n",*a);
	printf("%d\n",**a);
	printf("%d\n",*a[0]);
}

-1076368320
-1076368320
1
-1076368320
1
1
Last edited on
closed account (iw0XoG1T)
@rocketboy9000
my comment was not a criticism--I didn't understand. Thanks
Are nested pointers valid?
Ie.
1
2
3
4
int* a;
int* b;

*b = *a; // Is this even correct, or is there a problem with this? 




Edit: Accidentally clicked submit before ready.

ReEdit: Removed first question. Should have read before posting.
Last edited on
Yes, there is something wrong with that, pwnedu46. You didn't initialize anything. It they are pointing to valid locations, then there is nothing wrong with assigning the value of a's location to the value of b's location...
hmm, I guess the best way to explain it (even though it might be incorrect) would be to have the person think about variables like this:

Think of all variables as stored at a memory address. Don't worry about sizes, just locations and the data (or value) in the variable.


---------------------------------
| 123 | 124 | 125 | 126 |    <--- memory addresses
---------------------------------...
---------------------------------
| 001 | 123 | 001 | 000 |   <--- value
---------------------------------
1
2
3
4
5
6
7
8
9
10
11
12
13
int i = 1; // this variable was created at the location of "123" in memory
int *p = &i; // p actually equals the value 123, but is located at 124


std::cout << i; // this you should know. I'll print out "1" which is the value...

std::cout << &i; // "reference" this should output "123"(or location of i)...

std::cout << p; // this will output 123 also (or the location of i)

std::cout << *p; // "dereferenced pointer" this should print out 001
     //  or the value of the location it's pointing at


dynamic memory is a good reason to use pointers. Say you are creating a container with a new idea, but using a library isn't going to work for you, but need dynamic memory. How can we do that? With pointers...

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

int *q = new int[1];


// let's say p is pointing to the address at 125


q[0] = 1;


// now the value at the address 125 is 1

// Crap! I need more space in this array, but we are in the middle of the program...
// Oh, we are using pointers, so we can just resize the array
// There are many ways, I'm going the realloc route

// first make sure #include <cstdlib> is up there somewhere

int *check = (int*)realloc(q,2*sizeof(int));

if ( check != NULL ) {
       q = check ;
}

// you can do something if it couldn't allocate also

delete [] q;


That's where pointers are better in a way. You have direct control over the memory, but this control can cause many problems because people can screw things up easier.


.. let me know how much I got wrong...

-- edit: forgot (int*) when using realloc
Last edited on
you shouldn't use new or delete with realloc. use malloc and free.
I actually thought of that when I wrote it. I've never mixed them, but haven't looked into why.

-- edit: well, never before now.
Last edited on
ah, I think I see... new gets from free store while malloc gets from the heap, which may be the same depending, but may not be... is that about right?
^They both get it from the "heap" but the portion of the heap may be different for each one.
Pages: 123