Pointer Insomnia

Started by
19 comments, last by blanky 18 years ago
If you have no need to modify a variable that is not a POD(int,char,float,etc..) type your generally better off passing it by a constant reference than simply by value.
moe.ron
Advertisement
Quote:Original post by moeron
If you have no need to modify a variable that is not a POD(int,char,float,etc..) type your generally better off passing it by a constant reference than simply by value.



However, there are times when it is better to pass something by it's address when it's a big structure or something. Take this example:
struct{   int a;   int b;   int c;   char *cSomeString;} SomeStruct;//look at these two functions prototypesvoid SomeFunction(SomeStruct StructVariable);void SomeFunction(SomeStruct *StructPointer);


with the 1st functions, the compiler will have to copy the whole structure to SomeFunction, whereas, with the 2nd function, it will only have to pass the pointer address, which is just a register (or 1 space on the stack).

So, basically, if you have a large structure, sometimes you should pass by pointer (or reference) to save on performance.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Quote:Original post by CTar
You pass references if you just want to avoid the unnecessary copy, an reference can be though of as just an alias. The interresting thing about a reference is this:
int mynum = 9;
int& mynum_ref = mynum;
mynum_ref = 9;
&mynum_ref = address of mynum

A reference resides at its own address. What thinking of are union members.
Okay guys, I really appreciate the help you've given me, I've finally (almost) learned what I've never come around to learning. But anyways, I seem to be having some problems with the following, I might not be able to recreate the situation entirely 100 percent correct, but I think you'll catch on. So it's got to do with functions, well, not really. Watch, say we have:

void function(int *apples, int &oranges, int bananas){   // stuff}


So we're accepting three arguments, a pointer to an int, a reference of an int, and an integer called bananas. So what's the problem? Well, it's pretty complicated. So, we know that we can (Can we?) pass other things besides that, for example

function(&var1, *var2, var3);


Right? So basically what we're doing is allowing the function to modify var1 and var2's values right? Anyways, we could also (Er, can we? Would it be different?) pass this stuff:

function(*var1, &var2, var3);


Er, could we? I have the slightest feeling that var1 would be a pointer to a pointer, cause it's accepting a pointer in the first place, er, so would you do this? (If var1 is already a pointer (int *var1)).

function(var1 /*etc*/);


So basically, I'm confused as to what to pass how. And it gets more confusing to me when we're actually using the variable within the function, I've seen source that for example, you pass a pointer, and treat it as a pointer within the function

void function(int *apples, int &oranges, int bananas){   *apples = *apples++;   // etc}


However, at the same time, I've seen this happening

void function(int *apples, int &oranges, int bananas){   apples blah blah blah // instead of *apples   // etc}


Hmm...apples without the little pointer operator would mean it's address right? and *apples is the actual value of apples? But then, what would &apples be? Isn't that also the address of apples? Or what it points to I mean, unless one is the address of the pointer and one is the address of what it points to? Is there even such thing? I don't think a pointer has an address but then again what do I know.

Then there's the

void function(int *apples, int &oranges, int bananas){   &apples blah blah blah // instead of *apples or apples   // etc}


So, here we're modifying apples' value? That is, the value of the variable it points to? Man, I'm very confused and I know that you guys are getting this a different way than what I mean, if I could only find that one thread...but I have no idea of what forum of what site it'd be in. It was something like, 'if one of the function's arguments is a pointer, and you pass a pointer, then it'd be a pointer to a pointer', something like that, obviously I'm not saying that's right, but it was something like that, a chart, so I could know what to pass and how to treat each thing. I'm sorry guys, I have a feeling I don't make sense and this is kind of confusing, so, nevermind :'(

The forum thread said something like this, I don't remember correctly at all so this is most likely wrong:

If you have

int *thing;

and you have function prototype

function(int *arg1);

If you pass it like so

function(int *thing);

It'd treat it X way

If you pass it like so

function(int thing);

It'd treat it Y way

Sorry for the confusion guys
Quote:Original post by blanky
Sorry for the confusion guys


Yeah, you are very confused.

A pointer (e.g.: int *apples) is a variable. All variables and anything that holds data, such as the above, has to itself have some memory associated with it to be *able* to hold other data. apple has an address (== memory) for itself, aswell as what it currently holds - an address of another variable. When you use the ampersand on apple (&apple) you are producing the address of the variable apple. When you use the variable apple itself (apple), you are exposing the address of the variable it currently holds (or points to; the pointee). When you use the dereference operator on apple (*apple), you're applying the operator not to the apple variable, but to the address (of another variable) apple currently holds, essentially, you're accessing the final-value (an int) of the variable that apple currently holds, or points to.

I rec you watch this video: Binky Pointer Fun Video [grin]

EDIT: The following is a group of links that teach-up on pointers:

more Pointers
some more Pointers
and even more Pointers

The later one is one that I read through a couple years ago when I was learning pointers too.

- xeddiex
one..
:'( I have a feeling I'll never get this, thanks for being so kind though, I'll keep trying :'( Thanks for the links and help :')
Quote:Original post by blanky
:'( I have a feeling I'll never get this, thanks for being so kind though, I'll keep trying :'( Thanks for the links and help :')


Don't feel that way man. I too, was once in your situation. I thought I would never, ever learn to use or understand how pointers work. I just kept on trying and never gave up. I posted questions on it, here (under another name), and one day, it just finally clicked. Pointers are VERY easy to work with once you know them. They are also extremely powerful. I cannot imagine working without them in C, and maybe even C++. I started with C - for 3 years, and now I'm currently learning C++. I can happily skip the pointers part though, hehe, thanks to my previous experience in C.

Just don't get discouraged, it's normal to feel like this is an extereme topic to comprehend and that you'll never get it, but, trust me, if you don't give up, you'll eventually get it too. It's not a matter of IF, it's a matter of WHEN.

- xeddiex
[p.s, Don't be afraid to ask questions - someone will always be willing to help you out]
one..
Original post by blanky
void function(int *apples, int &oranges, int bananas){   apples blah blah blah // instead of *apples   // etc}


Okay, remember that apples is a copy of a pointer, so modifying apples does not change the address stored in your passed pointer. Additionally, I've noticed you've been referring to the concept of pointer-to-pointers in your post. I'm pleased to announce that none of your examples use pointer-to-pointers. If you don't want to allow the address stored in apples to change, declare it as an int* const apples (not to be confused with const int* apples or int const* apples). This notation makes it so that the address stored in a pointer can never change. The only real differences between a constant pointer and a reference is that a constant pointer can be deleted1, and pointers can be used for pointer arithmetic.


function(*var1, &var2, var3);


Don't worry, you can't pass a non-pointer to a pointer parameter, nor the address of a variable to a reference.

There are more parts to this subject, but try to wrap your head around this first.

1Well, a reference can be deleted, but you'd need to use a little trickery to do it; a trick that is vile.
Pointer are one of those things that, once you finally get it, it all clicks into place. When you understand it, you'll be like, "Ahh, it all makes sense now" and you'll feel like you can do anything. Understanding pointers leads to a deeper understanding of computers in general as well.

As for your examples, there's a few problems. Let me show some examples that might or might not help.

int Var1 = 1;  int Var2 = 2;int Var3 = 3;// I use 'p' in front to denote a pointer, and 'r' to denote a referencevoid func1(int *pParam1, int &rParam2, int Param3);// to call func1, the 1st parameter must be a pointer to int type, the other two must be int types// this is validfunc1(&Var1, Var2, Var3);// you must take the address of one of the variables (Var1) //and pass it as a pointer.  Now, you are literally passing the //address of Var1 to func1// The program will also pass the address of Var2 as the second parameter since it is a reference, but it is all hidden from you by the compiler.// Var3 is just passed by value, so it is actually sending 3 as the value to func1void func1(int *pParam1, int &rParam2, int Param3){// to change the value passed by pParam1, you have to dereference it with the * operation    *pParam1 = Param3;    // now you can change the actual value of rParam2 as well    // but you don't need to dererefernce it    rParam1 = Param3;    // this next line does nothing, since the actual value of Param3 won't change when you exit func1    Param3 = 0;}// the below will ***NOT*** workfunc1(*Var1, &Var2, Var3);// to use the * operator, the variable must have been a pointer, but Var1 is an int// &Var2 won't work because you must pass an int to the function, but you are now passing a pointer to an int, and the compiler will barf// Var3 is OK

now, what will the following program do?

int main (void){    int Var1 = 1;    int Var2 = 2;    int Var3 = 3        printf("Variables are %d %d %d\n", Var1, Var2, Var3);         func1(&Var1, Var2, Var3);    printf("Variables are %d %d %d\n", Var1, Var2, Var3);    }


I hope I helped.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

One of the most important ideas for understanding poitners ... a picture.

DRAW the layout of you objects in memory on a piece of paper ... using a fairly standard size box for each byte, inside the box, write what is stored IN the memory, above the box write the address of that memory.

so if I have:

int x = 3;
char text[] = "123";

I might draw it like:

0x80284852
---------------------
| 03 | 00 | 00 | 00 |
---------------------

0x80284856
---------------------
| 31 | 32 | 33 | 00 |
---------------------

And I usually don't worry about endianness until it matters. In the above, I wrote the hex values seperate, which I only do in real life when I'm starting out, or very concerned about exact byte placement ... normally I would just do:

0x80284852
-------------
| 3 |
-------------

0x80284856
-------------
| '123\0' |
-------------

And then we add the idea of a pointer and a reference to this system:

int x = 3;
char text[] = "123";
int *currentValue = &x
char *currentLetter = text; // an array name by itself is the same as a pointer to the first item.

0x80284852
-------------
| 3 |
-------------

0x80284856
-------------
| '123\0' |
-------------

0x80284860
-------------
| 0x80284852|
-------------

0x80284864
-------------
| 0x80284856|
-------------

See how I very clearly distinguish which are pointers, by putting strange numbers that start with 0x80 in the box (that's just an arbitrary fake address, because rarely in your program do you use ints over 2 billion).

I also typically draw arrowed lines from the pointer box to the box it points to ... showing the logical relationship. I use pencil for these lines when debugging an algorithm (as I do for the values in the boxes) because they may change while running).

References get a little harder if you are trying to correctly model them in terms of compiler treatment, but when it comes to function passing, I model them EXACTLY as I would const pointers in the diagram.

0x80284864 (ref)
-------------
| 0x80284856|
-------------

When using both pen and pencil (I always use pen as personal habit, unless I need rewriting), I write const values and reference lines in pen ... since they don't change.

This topic is closed to new replies.

Advertisement