Page 1 of 1

Pointer help

Posted: Wed Aug 12, 2009 3:09 pm
by derbon
Hi. I as anybody new to c++ dont understand pointers, like i know how to declare pointers and what they are. BUT WAT DA HECK DOO WEE USE DEM FOR?

i use pointers in allegro like:
BITMAP *bitmap;
SAMPLE *sample;
MIDI *midi;
. . .

soo umm help

Re: Pointer help

Posted: Wed Aug 12, 2009 4:04 pm
by wearymemory
http://stackoverflow.com/questions/5727/understanding-pointers wrote:Pointers is a concept that for many can be confusing at first, in particular when it comes to copying pointer values around and still referencing the same memory block.

I've found that the best analogy is to consider the pointer as a piece of paper with a house address on it, and the memory block it references as the actual house. All sorts of operations can thus be easily explained.

I've added some Delphi code down below, and some comments where appropriate. I chose Delphi since my other main programming language, C#, does not exhibit things like memory leaks in the same way.

Allocate memory
Get an entrepreneur to build your house, and give you the address to the house. In contrast to the real world, memory allocation cannot be told where to allocate, but will find a suitable spot with enough room, and report back the address to the allocated memory.

In other words, the entrepreneur will choose the spot.

Code: Select all

THouse.Create;
Keep a variable with the address
Write the address to your new house down on a piece of paper. This paper will serve as your reference to your house. Without this piece of paper, you're lost, and cannot find the house, unless you're already in it.

Code: Select all

var
    h: THouse;
begin
    h := THouse.Create;
    ...
Copy pointer value
Just write the address on a new piece of paper. You now have two pieces of paper that will get you to the same house, not two separate houses. Any attempts to follow the address from one paper and rearrange the furniture at that house will make it seam that the other house has been modified in the same manner, unless you can explicitly detect that it's actually just one house.

Note This is usually the concept that I have the most problem explaining to people, two pointers does not mean two objects or memory blocks.

Code: Select all

var
    h1, h2: THouse;
begin
    h1 := THouse.Create;
    h2 := h1; // copies the address, not the house
    ...
Freeing the memory
Demolish the house. You can then later on reuse the paper for a new address if you so wish, or clear it to forget the address to the house that no longer exists.

Code: Select all

var
    h: THouse;
begin
    h := THouse.Create;
    ...
    h.Free;
    h := nil;
Here I first construct the house, and get hold of its address. Then I do something to the house (use it, the ... code, left as an exercise for the reader), and then I free it. Lastly I clear the address from my variable.

Dangling pointers You tell your entrepreneur to destroy the house, but you forget to erase the address from your piece of paper. When later on you look at the piece of paper, you've forgotten that the house is no longer there, and goes to visit it, with failed results (see also the part about an invalid reference below).

Code: Select all

var
    h: THouse;
begin
    h := THouse.Create;
    ...
    h.Free;
    ... // forgot to clear h here
    h.OpenFrontDoor; // will most likely fail
Using h after the call to .Free might work, but that is just pure luck. Most likely it will fail, at a customers place, in the middle of a critical operation.

Memory leak
You lose the piece of paper and cannot find the house. The house is still standing somewhere though, and when you later on want to construct a new house, you cannot reuse that spot.

Code: Select all

var
    h: THouse;
begin
    h := THouse.Create;
    h := THouse.Create; // uh-oh, what happened to our first house?
    ...
    h.Free;
    h := nil;
Here we overwrote the contents of the h variable with the address of a new house, but the old one is still standing... somewhere. After this code, there is no way to reach that house, and it will be left standing. In other words, the allocated memory will stay allocated until the application closes, at which point the operating system will tear it down.

A more common way to get this method is just to forget to free something, instead of overwriting it as above. In Delphi terms, this will occur with the following method:

Code: Select all

procedure OpenTheFrontDoorOfANewHouse;
var
    h: THouse;
begin
    h := THouse.Create;
    h.OpenFrontDoor;
    // uh-oh, no .Free here, where does the address go?
end;
After this method has executed, there's no place in our variables that the address to the house exists, but the house is still out there.

Freeing the memory but keeping a (now invalid) reference
Demolish the house, erase one of the pieces of paper but you also have another piece of paper with the old address on it, when you go to the address, you won't find a house, but you might find something that resembles the ruins of one.

Perhaps you will even find a house, but it is not the house you were originally given the address to, and thus any attempts to use it as though it belongs to you might fail horribly.

Sometimes you might even find that a neighbouring address has a rather big house set up on it that occupies three address (Main Street 1-3), and your address goes to the middle of the house. Any attempts to treat that part of the large 3-address house as a single small house might also fail horribly.

Code: Select all

var
    h1, h2: THouse;
begin
    h1 := THouse.Create;
    h2 := h1; // copies the address, not the house
    ...
    h1.Free;
    h1 := nil;
    h2.OpenFrontDoor; // uh-oh, what happened to our house?
Here the house was torn down, through the reference in h1, and while h1 was cleared as well, h2 still has the old, out-of-date, address. Access to the house that is no longer standing might or might not work.

Buffer overrun
You move more stuff into the house than you can possibly fit, spilling into the neighbours house or yard. When the owner of that neighbouring house later on comes home, he'll find all sorts of things he'll consider his own.

(hard to give a concrete example to, presumably, the THouse type has been written correctly, will get back to this one).

Linked Lists
When you follow an address on a piece of paper, you get to a house, and at that house there is another piece of paper with a new address on it, for the next house in the chain, and so on.

Code: Select all

var
    h1, h2: THouse;
begin
    h1 := THouse.Create('Home');
    h2 := THouse.Create('Cabin');
    h1.NextHouse := h2;
Here we create a link from our home house to our cabin. We can follow the chain until a house has no NextHouse reference, which means it's the last one. To visit all our houses, we could use the following code:

Code: Select all

var
    h1, h2: THouse;
    h: THouse;
begin
    h1 := THouse.Create('Home');
    h2 := THouse.Create('Cabin');
    h1.NextHouse := h2;
    ...
    h := h1;
    while h <> nil do
    begin
        h.LockAllDoors;
        h.CloseAllWindows;
        h := h.NextHouse;
    end;

Re: Pointer help

Posted: Wed Aug 12, 2009 7:46 pm
by hurstshifter
Pointers can be very confusing at first. Essentially, a pointer is a data type which stores the address in memory of some variable/object/etc... For example, lets say that you have an integer called 'age' stored at memory adress 0x10FE in memory. Lets say that the value of this integer is 45, like so...

0x10FE
--------
45


Now, lets pretend that we also have an integer pointer called pAge that we want to 'point' at the age variable we just declared. We do this by saying...

int *pAge = &age;


At this point you may be asking yourself "Why the ampersand(&) before age?". We do this because a pointer's purpose is to store an address in memory. By using the '&' before a variable we are telling the compiler to return the variable's address rather than its value. Therefore, pAge now should equal the address of age. Let's pretend that the memory address of pAge is 0x1004. pAge would now look something like this...

0x1004
--------
0x10FE


At this point we can now do a few interesting things... We can directly modify age...

Code: Select all

age = 12;
We can indirectly modify it by 'dereferencing' the pointer (essentially telling it to modify the value being stored at the address the pointer is currently holding)

Code: Select all

*pAge = 12;
We can also tell pAge to point at a completely different variable (as long as it is the same type of the pointer, in this case int)

Code: Select all

int year = 2009;

pAge = &year;


Here's something else to think about. When you pass an integer (or any variable for the most part) to a function and that function makes a change to the integer, are you actually modifying the integer itself? (assuming you are not passing by reference of course, which is a whole other topic). No, you aren't. For example...

Code: Select all


void func1(int a)
{
   a += 1;
}

int main()
{
    int a = 5;
  
    func1(a);

    printf("%d", a);

    return 0;
}



This program will simply print the number 5. You passed int a to func1() but is essentially copying the value of int a into the formal parameter of func1(). Now do this...

Code: Select all


void func1(int *a)
{
   *a += 1;
}

int main()
{
    int a = 5;
    int ptrA = &a;

  
    func1(ptrA);

    printf("%d", a);

    return 0;
}



Same results? Try it and see for yourself :). By passing the pointer to the function you are able to indirectly modify the value of a. Pretty cool huh?



Sorry if I messed up on any of this explanation but this is probably the most basic example I could think of.

Re: Pointer help

Posted: Thu Aug 13, 2009 12:41 pm
by zeid
Pointers are used to keep things lean and mean in your program, it's kind of sad but they usually aren't described to beginners to well (IMHO). There are loads of interesting ways of using pointers to keep the program from doing unneccassary computations and memory allocation.

They can be used with arrays, and parsing the location of an entity rather then the entire entity...

Code: Select all

#include<iostream>
//for getch()
#include<conio.h>

using namespace std;

class Example
{
public:
	Example::Example()
	{}
private:
	int i_number;
	float f_number;
	char c_char;
};

int main()
{
	Example example = Example();
	Example *p_example = &example;
	cout<<"memory taken by example class "<<sizeof(example)<<"\n";
	cout<<"memory taken by example pointer "<<sizeof(p_example);
	getch();
}
Take this sample code, 'p_example' is the pointer to the entity 'example', if you add or remove the number of variables making up 'example': i.e added an int a_array[100] you will find that it's memory allocation increases (as is outputted), however it's pointers size does not. (It only has data allocated to it to point to the location that the memory starts being allocated for 'example').

The house anaology is a good one, lets say you wanted to return an 'example' class from a function. You could create a pointer to the class and return that instead to reduce the amount of memory you are having to use (as you are effectively duplicating the class otherwise).

There are alot more ways to use pointers, they can be used in situations where you need arrays and there are heaps of C++ quirks worth exploring in that regard.

I'm sure I'm repeating alot of people but meh...

Re: Pointer help

Posted: Thu Aug 13, 2009 3:19 pm
by Kros
wearymemory wrote:<snip>
That is a very cool analogy, and one I hadn't seen before.

Re: Pointer help

Posted: Thu Aug 13, 2009 6:12 pm
by Sanshin77
When I got to pointers I couldn't understand them either, here's what I did.

I read through the "tutorials" in the link below, tried to remember the syntax, even though I didn't completely understand the whole concept. Then I continued my book, writing and analyzing the code as always and eventually It suddenly "clicked" and I understood it, it didn't take too long either.

Link: http://www.cs.ucr.edu/~pdiloren/C++_Poi ... relive.htm

Click here to see the hidden message (It might contain spoilers)
My main problem was "Why the hell do I need them", the short answer to that is that it's a lot faster to give someone an address of {THING1}, rather than copying the whole {THING1} around all the time. When some part of your program have a pointer(address) to {THING1} they can all do stuff with it, rather than everyone having their own copy of {THING1}.
( {THING1} could be anything.)