Sign in to follow this  
Dhaos

Purpose of Pointers, a more in depth look

Recommended Posts

Dhaos    122
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
Molle85    172
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
MaulingMonkey    1730
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
Sneftel    1788
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
Dhaos    122
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
Sneftel    1788
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
rip-off    10979
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
lordcorm    100
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
Dhaos    122
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
daviangel    604
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
Dhaos    122
That was quite informative. Clears up the reason why references exist. I heard a copy was made if you try to change an external value inside a function. Does this only occur when you pass a value into the parameter or is a copy made when you change a global from *within* the function as well (a function that takes no parameters, just does default calculations on a global).

Share this post


Link to post
Share on other sites
LordShade    251
I have another good case for pointers. Let's say you have 3 structures you're written to a file in their binary form. Then you can just load the file into memory and munge your pointers to the proper index.


char* pLoadedFileBuffer;

STRUCT1* pStruct1;
STRUCT2* pStruct2;
STRUCT3* pStruct3;

pStruct1 = reinterpret_cast<STRUCT1*>(pLoadedFileBuffer);
pStruct2 = reinterpret_cast<STRUCT2*>(pLoadedFileBuffer[SIZEOF(STRUCT1)]);
pStruct3 = reinterpret_cast<STRUCT3*>(pLoadedFileBuffer[SIZEOF(STRUCT1) + SIZEOF(STRUCT2)]);


Voila! You have your structs all back without having to write routines for loading each individual item.

'Course someone says this is "An overly complex example" but it's a perfect example of where pointers can truly be handy and effective.

Happy coding.

Share this post


Link to post
Share on other sites
oler1s    585
Quote:
I heard a copy was made if you try to change an external value inside a function.
No. The only variables you can change inside a function are those that in scope. Such a variable is globally available, or the function is a member function of a class or structure and is accessing a member variable. Either way, they do not get copied.

Quote:
Does this only occur when you pass a value into the parameter
Yes. The copy occurs in passing the parameter by value.

Share this post


Link to post
Share on other sites
Valderman    513
This:
Quote:
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.
...is obviously incompatible with this:
Quote:
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.
I don't know why Stroustrup would say such a thing, but it's just plain wrong. An invalid pointer is NULL, which is not equal to 0. This means that using 0 instead of NULL is a bug in your code, period. There are even plans for introducing a nullptr keyword in the next version of the C++ standard, to combat this bad behaviour.

Share this post


Link to post
Share on other sites
ToohrVyk    1596
Quote:
Original post by Valderman
I don't know why Stroustrup would say such a thing, but it's just plain wrong.


It's perfectly correct, as per the standard, 4.10 §1. The basic idea is that the compile-time integer constant 0 gets converted by the compiler to a null pointer when evaluated in a pointer context (such as ptr == 0).

Share this post


Link to post
Share on other sites
Valderman    513
Quote:
Original post by ToohrVyk
Quote:
Original post by Valderman
I don't know why Stroustrup would say such a thing, but it's just plain wrong.


It's perfectly correct, as per the standard, 4.10 §1. The basic idea is that the compile-time integer constant 0 gets converted by the compiler to a null pointer when evaluated in a pointer context (such as ptr == 0).
It still makes for less readable code, and all compilers might not be in on that part of the standard. Both MSVC and GCC sometimes have interesting interpretations of these things.

Share this post


Link to post
Share on other sites
DevFred    840
Quote:
Original post by Valderman
It still makes for less readable code, and all compilers might not be in on that part of the standard.

The last standard is 10 years old. I doubt any recent compiler could have trouble with the issue.

Share this post


Link to post
Share on other sites
daviangel    604
Quote:
Original post by Valderman
Quote:
Original post by ToohrVyk
Quote:
Original post by Valderman
I don't know why Stroustrup would say such a thing, but it's just plain wrong.


It's perfectly correct, as per the standard, 4.10 §1. The basic idea is that the compile-time integer constant 0 gets converted by the compiler to a null pointer when evaluated in a pointer context (such as ptr == 0).
It still makes for less readable code, and all compilers might not be in on that part of the standard. Both MSVC and GCC sometimes have interesting interpretations of these things.

Then use nullptr if you have to name that which should not be named-LOL!

"
Should I use NULL or 0?

In C++, the definition of NULL is 0, so there is only an aesthetic difference. I prefer to avoid macros, so I use 0. Another problem with NULL is that people sometimes mistakenly believe that it is different from 0 and/or not an integer. In pre-standard code, NULL was/is sometimes defined to something unsuitable and therefore had/has to be avoided. That's less common these days.
If you have to name the null pointer, call it nullptr; that's what it's going to be called in C++0x. Then, "nullptr" will be a keyword.
"


[Edited by - daviangel on April 25, 2008 6:18:00 AM]

Share this post


Link to post
Share on other sites
Valderman    513
Quote:
Original post by daviangel
Quote:
Original post by Valderman
Quote:
Original post by ToohrVyk
Quote:
Original post by Valderman
I don't know why Stroustrup would say such a thing, but it's just plain wrong.


It's perfectly correct, as per the standard, 4.10 §1. The basic idea is that the compile-time integer constant 0 gets converted by the compiler to a null pointer when evaluated in a pointer context (such as ptr == 0).
It still makes for less readable code, and all compilers might not be in on that part of the standard. Both MSVC and GCC sometimes have interesting interpretations of these things.

Then use nullptr if you have to name it:

"
Should I use NULL or 0?

In C++, the definition of NULL is 0, so there is only an aesthetic difference. I prefer to avoid macros, so I use 0. Another problem with NULL is that people sometimes mistakenly believe that it is different from 0 and/or not an integer. In pre-standard code, NULL was/is sometimes defined to something unsuitable and therefore had/has to be avoided. That's less common these days.
If you have to name the null pointer, call it nullptr; that's what it's going to be called in C++0x. Then, "nullptr" will be a keyword.
"
Sure. Personally, I wouldn't care if it was called the DivideByZeroPtrOHNOES or whatever, as long as you can plainly see that it's a NULL pointer and not a zero integer. Though I might just have been reading too much C code.

Share this post


Link to post
Share on other sites
johnl87    133
If you do any assembly level programming, you eventually realize that everything is an address. Every time you call a function, your parameters get copied unto the stack. Lets say you have a struct that has 100 integers, that makes your code 100 integers larger if you pass the struct by value into a function. If you throw in a reference, or a pointer to the struct, it only copies the address of the struct.

Also memory allocation plays a huge role when you don't know how much of something you'll have, i.e. linked lists. That way, you can allocate space at runtime. (You can allocate a huge chunk or however much you think you'll need before hand in an array of some sort, but allocating during run time makes it more efficient.)

Static has two meanings depending on where it's used. This is coming from a C perspective, but I'm not 100% on C++, can anyone confirm this?

If you declare a variable as static within a function or one that normally has no linkage (i.e. can't be accessed outside that file or block), it will be initialized only once at the beginning of the program and will exist until the program exits.

If you declare a function or variable outside of a block as static, you change the linkage from external to internal to the file. Which means that function or variable is only accessible from the file it is declared in. This is useful when you want to hide the implementation of something from the user.

Share this post


Link to post
Share on other sites
cygil    122
Major uses of pointers in C/C++:

They are used to implement many basic data structures that require "chains of references", such as linked lists, trees, and graphs.

They are used to refer to objects that are dynamically allocated on the heap with the malloc call (C) or the new operator (C++).

They are used to iterate through arrays and other "linear" data structures.

They are used to pass or return references to large objects to or from a function, where passing the whole object would be expensive.

They are sometimes passed to emulate "out" parameters in C, ie parameters that the called function is expected to modify.

In C++, they are used to invoke polymorphic behaviour. For example, assigning between type compatible pointers is safe; assigning objects by value can cause unintended slicing and other undesirable mutilation of your objects. And you can use pointers to store "collections of things", where the things are all from a common base class, and method calls are polymorphic and adapted to each class of object (although this pattern, although hyped in OO circles, is less common in C++ than you might think.

There's probably many more uses. They are essential; read enough C/C++ code and you'll see them everywhere.

Share this post


Link to post
Share on other sites
wodinoneeye    1689


I use them all the time in network (C) code to point to multiple message structures sent in one packet (using a char pointer with an offset and then casting it to a pointer of one of my many different message structs).

Similarly I use them in object attribute management where I maintain my own heap for each object (which is one BIG struct including the heap containing many secondary nodes -- like object attributes). Maintaining a local heap makes rolling the object in and out of memory and sending it to a different server processing node much simpler and faster (almost no serialization needed bacause all the internal pointers are based on offsets from the top of the objects heap)

I use pointers for the few custom script languages used in my simulations -- the parser reads char by char and in another its a bytecode interpretor that steps thru precompiled 'code' using byte pointers.

My project is rather CPU intensive and uses huge amounts of memory, so making data as compact as possible is important (more fits, less to transmit, fewer cache misses). Higher level constructs would be wasteful and far slower and my heavy use of pointers allows me do do exactly what I need done without overhead of more generalized solutions.



Share this post


Link to post
Share on other sites
RDragon1    1205
Quote:
Original post by Valderman
Quote:
Original post by ToohrVyk
Quote:
Original post by Valderman
I don't know why Stroustrup would say such a thing, but it's just plain wrong.


It's perfectly correct, as per the standard, 4.10 §1. The basic idea is that the compile-time integer constant 0 gets converted by the compiler to a null pointer when evaluated in a pointer context (such as ptr == 0).
It still makes for less readable code, and all compilers might not be in on that part of the standard. Both MSVC and GCC sometimes have interesting interpretations of these things.


You should check what you say before you say it. In msvc I see

#define NULL 0

and I have never used the NULL macro, using it seems overly verbose and as macros including NULL are not pretty and the convention of ALL_CAPS is meant to draw your attention to them, I agree that they're best avoided unless absolutely needed.

The days of blaming standards compliance are essentially gone for C++98. The big players pretty much have it down really well.

Share this post


Link to post
Share on other sites
korsen    122
just showing what i know of pointers:

pointers, point to a values MEMORY ADDRESS.
changing it will change the value held in that address, therefore saving space.

I've used pointers to have users change class data. It's a fairly powerful tool.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this