Jump to content
  • Advertisement
Sign in to follow this  
Dhaos

Purpose of Pointers, a more in depth look

This topic is 3707 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am well aware of how these work and how to use them without crashing my applications. But... what I'm asking is why do you need them? The only time I use them is when an external library function forces me to. (aka DirectX/C/C++ library functions) I just don't "get it". Many examples I have seen in which a pointer is used, a global variable would help just as much if not more (specifically with coordinates and data storage that has to be used constantly throughout the program) Do pointers simply help manage the trade off between using more RAM/Constant Memory Usage (globals) and CPU usage?(locals/constantly creating and deleting them every cycle to keep them in memory for a short as possible) Another keyword that baffles me is "static" How does the application keep its value initialized only once? (If I remember correctly it keeps whatever the last value was) Does that variable stay in memory like a global or is there something I am missing? Even when I dabbled in AI programming awhile back I had a hard time finding a use for them. Back then I kept a small series of globals to determine actions (or rather what it was planning to do, attack, run, heal, etc) Anyone who can chime in on this and elaborate more? Wikipedia gave piss poor examples of why they are needed. I just *know* I am missing one of those basic "duh" things, but alas...I want more proper clarification.

Share this post


Link to post
Share on other sites
Advertisement
first of all... Globals are evil =)

And there is a lot of times when you want to access memory manually...
for example, D3DCOLOR is a typedef of unsigned int, if you want to access the ARGB separately you can either bit shift, or you could use pointers.

D3DCOLOR color;

unsigned char a,r,g,b;

a = ((unsigned char*)&color)[3];
r = ((unsigned char*)&color)[2];
g = ((unsigned char*)&color)[1];
b = ((unsigned char*)&color)[0];


there are not many situations when you MUST use a pointer, but it's good to use sometimes.

Share this post


Link to post
Share on other sites
The problem with global variables is that because they can be accessed from everywhere, they're harder to debug -- ruling out what isn't causing the problem becomes exponentially harder.

"static" variables within a class function very similarly to globals, yes. If they're private, they're also a lot less evil -- you can rule out everything but the class and it's friends as being the (direct) cause of changes to said variable.

A main necessary use of pointers is handling dynamic storage allocated with, for example, new[] and delete[] -- basically, when you don't know how many of a given item you want to store ahead of time. They're necessary to implement all the standard library containers, for example (std::string, std::vector, std::list, std::deque, etc...). Of course, half the point of using these things is so that you don't have to directly use the pointers yourself.

Share this post


Link to post
Share on other sites
Pointers and global variables have very little to do with each other. One is not an alternative to the other. Remove that correlation from your mind.

The best way to understand pointers is to implement a linked list class. Try that.

As for static (for that meaning of the keyword), think of static as simply a global variable which isn't declared as global scope. There are certain differences related to initialization order, but it's pretty much the same thing. You should think of static variables as global variables whose use is localized to a class or function.

Share this post


Link to post
Share on other sites
Ah the fabled linked lists. I remember studying those. I came into one peculiar problem in their design.

Take a strategy game: I would assume a linked list would be used to store say, all of the player units, and another would store all the enemy units, another for graphical effects etc.

How does one keep the data (that changes, say health for example) stored in said link list accessible throughout the application? Once a function exits, namely the one in which they were created, don't items created with new go out of scope and their data lost? Or did I miss read about how "new" actually works. Do objects created with new persist throughout the entire application until delete is called? If so that would explain a lot, if...not I'm still baffled as hell.

Share this post


Link to post
Share on other sites
Quote:
Original post by Dhaos
Once a function exits, namely the one in which they were created, don't items created with new go out of scope and their data lost?
No. If there is a local pointer which points to the memory, that pointer will of course go out of scope, but the pointed-to memory (which new allocated) will still be allocated.
Quote:
Or did I miss read about how "new" actually works. Do objects created with new persist throughout the entire application until delete is called?
Bingo.

Share this post


Link to post
Share on other sites
Quote:
Do objects created with new persist throughout the entire application until delete is called?


Exactly. In C++, new and delete allow you to have objects persist until you say so. Of course, that burdens you with the responsibility to say so at the right time.

I second Sneftel's suggestion. You won't "get" pointers until you use them, and a linked list is the classic application of pointers.

Share this post


Link to post
Share on other sites
Memory Management.

You will lower the amount of memory you use if you use pointers, because you dont have to allocate new memory to copy the variable to a different function, class, struct, ect... It technically dosnt give you much of a boost though, because your copied memory will fall out of the scope sooner or later.

Not speaking technically, but speaking hypothetically (as in not being literal), copying memory down a large function hierarchy is like playing that game you played in 4th grade. Where you would tell your neighbor a secret and it would be passed around the room, and then come out the other end as corrupt data. (NOT SPEAKING IN LITERAL TERMS)

But, then again, having direct access to the memory can be a bad idea in a multi-threaded environment where if you where in the middle of a function that modified a variable, and in the other thread, trying to read the variable, and they are both pointers to the same memory.... well, you get the idea (KABOOM!)
(Thread locking is the semi-solution to this)

just my 2 cents :P

Share this post


Link to post
Share on other sites
Well then, now I know how that works *finally*. This whole time I was under the impression even with new/delete that objects still died at the end of the function.

I really appreciate all of you for explaining that mystery to me. That actually makes pointers quite useful indeed!

For now I am satisfied. It's time to go back to coding with this new found and dangerous knowledge. I sense mass crashage in my near future. *scurries off*

Share this post


Link to post
Share on other sites
After a year of just sticking with C++ programming and more recently going back and learning C it's a lot clearer when to use them.
In a nutshell taken from the creator of C++ website:
"
4.13.3 Function Parameters (Value, Pointer or Reference)
AV Rule 116
Small, concrete-type arguments (two or three words in size) should be passed by value if changes made to formal parameters should not be reflected in the calling function.
Rationale: Pass-by-value is the simplest, safest method for small objects of concrete type. Note that non-concrete objects must be passed by pointer or reference to realize polymorphic behavior. See rules AV Rule 117 and AV Rule 118.
AV Rule 117
Arguments should be passed by reference if NULL values are not possible:
AV Rule 117.1 An object should be passed as const T& if the function should not change the value of the object.
AV Rule 117.2 An object should be passed as T& if the function may change the value of the object.
Rationale: Since references cannot be NULL, checks for NULL values will be eliminated from the code. Furthermore, references offer a more convenient notation than pointers.
AV Rule 118
Arguments should be passed via pointers if NULL values are possible:
AV Rule 118.1 An object should be passed as const T* if its value should not be modified.
AV Rule 118.2 An object should be passed as T* if its value may be modified.
Rationale: References cannot be NULL.
"
In my own words basically it's saying this. If your function needs to change something that's being passed to it use a reference otherwise a copy will be made(pass by value is the default) and nothing will be changed. I'm sure you've seen the version of the swap function that doesn't work?
Finally, if there is a possibility of what you are passing to the function can be NULL you have to use a pointer instead of a reference since you can't have a NULL reference!
If you are an old school C programmer you will see that they use pointers alot more often than others since references don't even exist in C they have to use pointers all the time they want a function to change values in the calling program.
Oh and of course dynamic memory allocation i.e use of malloc in C or new in C++.
And the other couple of times off the top of my head when you have to use them is proxy classes and self-referential structures or classes like the dreaded "linked list"!
So to recap if you are using C++ the way it's intended(prefer vector over array,etc) and making use of the STL containers that implement linked list already(so you really don't have to mess around making your own LL from scratch but most data structures courses make you and you should do it at least once yourself to get a feel for all the grief/work the STL is saving you from)or dealing with legacy code or hardware devices(low level code,directx) it should be rare for you to have to deal with pointers.

p.s. Here are some more good rules about pointers that may prevent an application crash in your near future!LOL!
Pointers & References
AV Rule 169
Pointers to pointers should be avoided when possible.
Rationale: Pointers to pointers are a source of bugs and result in obscure code. Containers or some other form of abstraction should be used instead (see AV Rule 97).
AV Rule 170 (MISRA Rule 102, Revised)
More than 2 levels of pointer indirection shall not be used.
Rationale: Multiple levels of pointer indirections typically produce code that is difficult to read, understand and maintain.
Note: This rule leaves no room for using more than 2 levels of pointer indirection. The word “shall” replaces the word “should” in MISRA Rule 102.
Relational operators shall not be applied to pointer types except where both operands are of the same type and point to:
• the same object,
• the same function,
• members of the same object, or
• elements of the same array (including one past the end of the same array).
Note that if either operand is null, then both shall be null. Also, “members of the same object” should not be construed to include base class subobjects (See also AV Rule 210).
Rationale: Violations of the above rule may result in unspecified behavior [10], 5.9(2).
AV Rule 173 (MISRA Rule 106, Revised)
The address of an object with automatic storage shall not be assigned to an object which persists after the object has ceased to exist.
Rationale: An object in a function with automatic storage comes into existence when a function is called and disappears when the function is exited. Obviously if the object disappears when the function exits, the address of the object is invalid as well. See Also AV Rule 111 and AV Rule 112.
AV Rule 174 (MISRA Rule 107)
The null pointer shall not be de-referenced.
Rationale: De-referencing a NULL pointer constitutes undefined behavior. [10] Note that this often requires that a pointer be checked for non-NULL status before de-referencing occurs.
AV Rule 175
A pointer shall not be compared to NULL or be assigned NULL; use plain 0 instead.
Rationale: The NULL macro is an implementation-defined C++ null pointer constant that has been defined in multiple ways including 0, 0L, and (void*)0. Due to C++’s stronger type-checking, Stroustrup[2] advises the use plain 0 rather than any suggested NULL macro.
AV Rule 176
A typedef will be used to simplify program syntax when declaring function pointers.
Rationale: Improved readability. Pointers to functions can significantly degrade program readability.


[Edited by - daviangel on April 20, 2008 6:55:52 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!