C++ Fundamentals Question

Aff64379e80eed342e80ba6fb92d340f
0
Kryogen 101 Jun 28, 2005 at 08:08

A fundamental question, if I may.

Variables are declared by setting them by type and name, then given values by assignment.

variable_type variable_name;
varable_name = value;

I understand this process very well, having grown up casually programming.

In C++, you can use the ampersand to look not at the variable, but at the memory address on the stack where the variable exists. To do this, most fundamental examples teach you to use pointers, which are variables that point to other variables.

variable_type variable_name;
variable_type *point_to_variable;
point_to_variable = &variable_name;

The only thing I don’t understand is: why? Why use a pointer to a variable? Why not just modify the variable itself? Why point to a spot in memory and read what is on the stack, rather than dealing directly with the variables themselves?

This is one aspect of programming I’ve never really understood. When I get into actually doing the graphical side of programming, I’m going to more-or-less use triangles. A triangle is built by using a matrix of verticies: [ x1, y1, z1, x2, y2, z2, x3, y3, z3 ]. When these get moved around, rotated, and so forth - shouldn’t I just be modifying the values themselves?

If anyone can provide a practical example and/or basic reasoning, I would greatly appreciate it. It is difficult for me to work without context and examples.

Many thanks,
-Kryogen

20 Replies

Please log in or register to post a reply.

760a6f5fe0bf771163e05e808716020b
0
NeZbiE 101 Jun 28, 2005 at 09:53

Talking about pointers, see the binky pointer video from Stanford. It’s really a lot of fun, and well explained ;-) http://cslibrary.stanford.edu/104/

Anyways, why are pointers used? Good question, here are some reasons:
1)Efficiency

Saves memory, runs faster, since it does not have to copy data (IE, function parameters)

2)Pointers can be used for strings, arrays, etc…

Ever use myArray[100] or something similar?
Try doing *(myArray+50) and see what comes up :-)!
myArray is essentially a pointer to the first block of memory where the data is stored, so the “+50” is essentially giving you the 50th index. Same thing for strings. Also, how would you pass on an array as a function parameter like a normal variable? You can’t really, you have to use pointers. If you don’t know how many elements will be in an array at compile-time, and need data from runtime (say, a value input by the user), how do you think you would do it?

3)Function parameters

Given:
void function(int data)
{ data+=5;
}

And the following:

int blob(0);
function(blob);
cout << blob;

What answer do you think you will recieve? It should display 0. To make it display 5, you could call “function(&blob);” instead, and modify the function appropriately for pointers.

So, there you have it, pointers are good for you =)

[Edit: Typo]

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Jun 28, 2005 at 16:14

Besides the above, pointers are great for dynamic memory allocation. If you have an array, but you don’t know how big it’s going to need to be when you write the program, you can use the “new” command to allocate memory for the array, using a variable as the size. This command gives you back a pointer to the memory.

In addition to this, pointers are useful for creating certain kinds of data structures. Consider the following:

struct MyStruct
{
   int some_data;
   MyStruct *next;
};

This allows you to have a single instance of MyStruct, which contains a pointer to another instance, which points to another one, and so forth (the last one has its pointer set to NULL). You have to use a pointer here; you can’t just have a variable of type MyStruct inside MyStruct, because it would cause an infinite recursion.

This data structure is called a linked list. It is similiar to an array in that they are both a (potentially large) list of pieces of data of the same type - but linked lists are more flexible because they can grow and shrink at run-time, and items can be inserted/removed very easily. (Compare this to an array - to grow or shrink it, you’d have to reallocate the memory and copy it all over to the new place every time you wanted to change the size!)

Linked lists are not the only data structures that can be created with pointers - you can also do more exotic things such as trees, graphs, tables, whatever you can imagine.

Aff64379e80eed342e80ba6fb92d340f
0
Kryogen 101 Jun 28, 2005 at 21:43

Reed –

Actually you brought up my next question. During my studies, this whle “new” thing. I don’t get it.

int *blah = new int;

Why?

Doesn’t “int blah;” work just as good?

From what I understand, it creates a pointer to a new integer value on the stack. But, during a function call, if the variable is created locally, wouldn’t it be dynamic anyway? As in be constructed when it beings, and torn down when the function ends?

Regards,
-Kryogen

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Jun 28, 2005 at 22:34

one reason to do this is that you do not always know how much memory you will need. for example : you read from a file that is stored on the disk. let’s say you are writing an image viewer that reads all kinds of images. what you could do know is have some fixed sized array that’s known to be big enough to hold all your image data (which is unlikely because who knows when there will be 64bit images). on the other hand you could allocate the memory needed for one image dynamically. you would basically use the c i/o functions to query how big the file is and then you allocate exactly that much memory via “new”.

there is less memory wasted this way in case some images are really small and you will never run into the problem that an image is actually too big and blows your image buffer.

of course there is a downside to this. variables on the stack have a well defined lifetime. once the function they were declared in returns they get poped off the stack and are gone. with dynamic memory you need to free that memory yourself, which as you can imagine is often forgotten.

void foo(){

  // after this ptr points to an array of 100 integer elements
  int* ptr = new int[100];
  
  // ...do some stuff...

  // here the function returns and the pointer gets poped off the stack
  // but not the data it pointed to so if you didn't delete the data between here  
  // and it's allocation the pointer will be lost and there is no way you can free 
  // the memory. if foo is called in a loop bad things are going to happen !
}
A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Jun 29, 2005 at 02:21

Furthermore, once you get into object-oriented programming, you will find that pointers are useful as “links” to other objects. For instance, say you are making a game and it has trees in it, with each tree represented by a C++ object. It would be very inefficient to have a copy of the tree’s vertices for each one, as a single tree could be several kilobytes of RAM. So instead, you have a single copy of the tree’s vertices, and each tree object contains a pointer to that data. And there are many other situations in which you would want one object to have a “link” (pointer) to another object, rather than a copy of it.

Aff64379e80eed342e80ba6fb92d340f
0
Kryogen 101 Jun 29, 2005 at 08:27

I really appreciate the attempts to help. :)

Being a complete and total newbie, I can only halfway understand what you guys are talking about. I’m going to be going through my 7-in-1 C++ For Dummies book (almost done with the first of the seven books) and through http://www.cplusplus.com tutorials. Hopefully I will then be able to understand what you guys mean in a little more light.

I apologize for asking such mundane, elementary questions. We all have to start somewhere. :) That being said, again, I really appreciate the help.

Again, I ask… why not use variables directly, rather than point to their memory location?

Case in point one - I need to modify the value of something.

void add_one(int* ptr) { return ptr++; }

This I understand and can see the value of using a pointer. You want to modify the variables themselves being sent to the function from where the call came from.

int main() { int x(0); add_one(x); cout << x; return 0; }

In this case “x” actually gets incremented by one, rather than staying zero.

But this is the only example I can think of where it has any use. Break it down for me like this…

Let’s say you have a structure for an RPG character. Your character has a certain constitution rating. You boot up the game and load your saved game, and during that process your characters statistics load.

Are you not just loading the character into some sort of global object that is persistant throughout the lifecycle of the game itself?

Why not just access the variables in the structure directly?

If NPCs need to be loaded who also have structures, wouldn’t you have to load them all at once anyway, so long as they were in the same “zone” or map as you were?

In your tree reference, wouldn’t you have to load every tree simultaneously, regardless of placement on the map or if they are in your current clipping plane/view?

In these cases, it to me, makes more sense to load everything statically into memory. I don’t understand dynamic loading of structures (objects one can see visually, like a tree or an NPC). Then again, I’m ignorant, so…

:)

-Kryogen

Aff64379e80eed342e80ba6fb92d340f
0
Kryogen 101 Jun 29, 2005 at 08:32

After re-reading what you wrote Reed, I thought about it some more.

So in other words, you have a data structure you are loading for object “Tree”. You load the tree object, complete with all the verticies necessary for rendering the tree properly. I think what you mean is that instead of having each tree load it’s own object into memory, you simply say “me? Oh I’m that tree over there. No need to load new information, just replicate that data there.”.

Does this not still consume memory when you create a new object to be rendered?

760a6f5fe0bf771163e05e808716020b
0
NeZbiE 101 Jun 29, 2005 at 13:35

Alright, let’s use a basic example:
You want to load a model from a file, to render it in your game.
You have code which loads 3ds files, and use it to load your various models.

However, when you are loading a file, you don’t know how many verticies (or texture coordinates or whatnot) there will be. So, the only way to go around this is to dynamically allocate an array at run time.

So, you ask, why not use Verticies[number_of_verticies_here]? Well, you want the same code to be able to load all 3ds files, and not just one example, no? Also, arrays like Vertex[100] are statically allocated, so you cannot have something like this:
-Read Number_of_verticies from file car.3ds
float bob[Number_of_vertices];
This is because the compiler needs to _know_ what the size of arrays/strings are if they are static.
Another thing about pointers is that they are fast. When you pass on a regular variable as a function parameter, the computer actually copies the variable into a new segment of memory as a local variable, not to mention that all changes to it are lost. My previous post details several other useful reasons for using pointers, as well as more information on arrays.

I hope this clears things up a bit.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Jun 29, 2005 at 16:02

Yes, in the tree example you still need a small piece of memory for each individual tree. But that will be no more than a few bytes - let us say 16 bytes for argument’s sake (12 bytes indicating the location of the tree, and 4 bytes for a pointer to the model). The model, then, which contains the actual vertex data, could be much larger - let us say 32 KB for argument’s sake (32 bytes per vertex, 1024 vertices). Now if you had a copy of the vertex data for every tree (let’s say 1024 trees), that would be 32MB of RAM tied up just by those trees. But if you use pointers to keep a single copy of the vertex data, this is just 48 KB total (32 KB for the vertex data, plus 1024 * 16 bytes = 16 KB for the individual tree objects). That is an enormous memory savings. (In case you were wondering: it is easy to use the graphics hardware to apply a geometric transformation to each vertex when rendering. Thus, the transformation needed to move the tree to each individual location is done by the hardware as the trees are rendered, without needing to modify the vertex data stored in RAM.)

48d5487f357fbcacc89e84720577f0ac
0
Steven_Hansen 101 Jun 30, 2005 at 16:20

I think this guy needs a basic example. It seems his impression of pointers is that they are used principally for integers. This is not the case - it is just easier to understand when presented with integers.

Let’s use strings instead! Assume CString is a class wrapper for strings.

Class CString; … something like that…
CString myString = “Here is a fairly short”; // All is good so far.

Now let’s say we want to append “string.” to myString. Without pointers we have:

CString append(CString first, CString second) {
  return first + second; // Assume + overload is already implemented.
}

// Then we make the call later like so:
myString = append(myString, CString("string."));

Ok. There is nothing technically wrong with this code. How many copies of strings were made? Well, since we passed all of the parameters by value, and returned by value, the compiler makes copies every time the data moves into the function or back.

Summary of unique strings created by the above code:
myString -> “This is a short”
first -> “This is a short”
CString -> “string.”
second -> “string.”
implicit return value -> “This is a short string.”
returned copy -> “This is a short string.”
myString assigned -> “This is a short string.”

Lots of duplicates here. Additionally, myString was not directly changed, instead its old value was thrown away, and another copy was made.

For short strings, this may be the easiest implementation. Let’s pretend that each string is a book instead… about 64MB or so. Now myString is huge! So, even appending the words, “The end!” to the string is going to require about 64*5 or 320MB of data - most of it being copied for no reason.

Let’s revisit the append function. This time we make it a member of CString and use pointers instead:

CString* CString::append(CString* val) {
  mString += val->mString;
  return this; // This is a trick for passing the function as an argument.
}

// And later the call...
CString theend("The End!");
myString.append(&theend);

Now assuming CString is a good implementation, we only copy theend to the end of the string pointed to by myString. The string in myString is *never* copied anywhere. So if it is 64MB, we don’t really use any more memory - or make any more copies. (STL has an implementation of string that works pretty well).

Hope this is straightforward.

Aff64379e80eed342e80ba6fb92d340f
0
Kryogen 101 Jul 01, 2005 at 02:37

That makes some sense now.

The jist I am getting is that, basically, using pointers that point to a variable already on the stack saves a lot of memory. If you pass by value (string1,2,3, or integer1,2,3) the function creates its own local copies / values and that takes up memory. Now in the example of a string, I can understand easily the example you gave (although the actual code I haven’t gotten familiar with yet, but I will be).

Not to beat the thread to death, but I do have another question, unrelated to thee above information: Header wrappers.

The dummies book glosses over the subject, and I haven’t found much online to help me either (even on cplusplus.com). It has something to do with having the include files loaded multiple times and causing problems. Anyone care to give me a little bit better explaination than the book?

If not, we can let the thread die. :)

Appreciated.

-Kryogen

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Jul 01, 2005 at 03:48

Yes, using pointers to data on the stack saves memory. The other main purpose of pointers is to allow you to manipulate data on the heap, which can’t be acessed without them. But like you say, we’ve already beat this subject to death :-) All I can say is that the usefulness of pointers will become clearer as you get deeper in to C++ and write more complex pieces of software.

As for your question about header wrappers, that is fairly simple. Suppose that you had a header called “vec3.h” defining a class called “vec3” (a three-dimensional vector). Now suppose you have two more headers, “class1.h” and “class2.h”, defining class1 and class2. Both of these classes include a member variable of type vec3, so you must include vec3.h in each header file:

// vec3.h
struct vec3 { float x, y, z };

// class1.h
#include "vec3.h"
class class1 {
  vec3 foo;
  // other stuff
};

// class2.h
#include "vec3.h"
class class2 {
  vec3 bar;
  // other stuff
};

Now what happens when you include both class1.h and class2.h into the same source file? The compiler sees the definition of vec3 twice - once when class1.h is included (and thus includes vec3.h), and once when class2.h is included (and thus includes vec3.h again). This causes a “duplicate definition” error.

There are various ways to solve this. For instance, you could make a rule that header files cannot include other header files. However, then anytime you wanted to include class1.h or class2.h in a source file, you would have to remember to also include vec3.h. If you have a lot of classes, this is a pain - you have to remember to include all the right files, and you have to do so in the right order.

Another way to solve the duplicate-definition problem is to use header wrappers. Basically, you use the preprocessor to ensure that if a header is included more than once, the second and later inclusions do not do anything.

The standard pattern for a header wrapper is:

// myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H
// normal header code goes here
#endif

How does this work? Well, when the preprocessor is working on a source file, suppose it sees #include “myheader.h” for the first time, so it begins to process myheader.h. The #ifndef asks the preprocessor whether there is a symbol called “MYHEADER_H” defined. There is not, so the #ifndef evaluates true (“if not defined”). The first thing that happens is that “#define MYHEADER_H”. Then all the normal header code is included.

Now suppose the preprocessor sees #include “myheader.h” a second time. Now, MYHEADER_H is defined, so when we hit the #ifndef, it evaluates false and jumps directly down to the #endif. All the header code is skipped; thus, no duplicate-definition errors occur.

Each header file uses a different symbol (usually the filename, with the .h changed to _H). Each source file is processed separately, so including a header in one source file doesn’t cause it to be ignored in another source file.

Hope this answers your question - and feel free to post anymore you may have.

760a6f5fe0bf771163e05e808716020b
0
NeZbiE 101 Jul 01, 2005 at 03:56

If your headers are included multiple times without the appropriate preprocessors, you will likely end up with some trouble (I assume this is what you mean by header wrappers).

Basically, it’s a good idea to have something like:

#ifndef _INCLUDE_FILE_
#define _INCLUDE_FILE_

//here be something

#endif //_INCLUDE_FILE_

To wrap your include files, to make sure the stuff isn’t defined multiple times (a big no-no). For example, try defining the same variable name twice, and you’ll end up with some errors! Of course, the _INCLUDE_FILE_ name can be whatever name you want it to be (you will most likely want it to be different for each include file), although you’ll likely want to keep some sort of convention for all your header files. The preprocessors are the stuff denoted by “#”. Basically, these are all evaluated at compile-time, instead of at run-time.

If you’re running MSVC, you can give something like the following a try (It will only include/read the file once during build):

#ifdef _MSC_VER
#if _MSC_VER > 1000
#pragma once
#endif
#endif

I hope this is what you were referring to. Preprocessors are really useful =)
Anyways, that must have been a pretty bad chopped up answer. Whatever, it’s 1:00 AM and I have a midterm today \^\^

[Edit: Reed beat me to it, with an even better explanation :-) ]

Aff64379e80eed342e80ba6fb92d340f
0
Kryogen 101 Jul 01, 2005 at 07:18

Thanks guys. :)

Sorry to take up all your programming time with mundane questions. But I guess it’s good to have a refresher every now and again for people to read. Not to mention help a noob. :)

Owe you guys.

-Zach

Aff64379e80eed342e80ba6fb92d340f
0
Kryogen 101 Jul 08, 2005 at 07:33

I thought of another question. Now that I understand passing variables by reference, creating new variables, and pointers to variables, I’ve moved on. So I ran into the same fundamental question everyone runs into at some point in their programming career: Bloodshed Dev-C++ or M$ C#?

I read the wiki @ http://www.devmaster.net/wiki/Languages_su…ting_games_with before I asked the question, like always, trying to do my homework before making a fool out of myself. Nevertheless, I was looking for some personal opinions here: Which do you prefer, and which is a better choice for starting from scratch and learning from the ground up? Does C# have better support through the DirectX SDK? Does it have better Windows platform support natively?

When I found out C# was free, and since it is the “new” thing, I figured since I’m still doing the fundamentals I might as well see about using it if it is a more powerful language.

Hope to hear from some of “y’all” (as we say in the south) soon.

-Kryogen

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Jul 08, 2005 at 07:54

this might entirely depend on what kind of person you are. c++ and c# are both c derivates and will seem very similar to you at first. c# is much more high level than c++ and introduces a lot of abstractions. c++ still lets you get to the bones of your system by leaving the door open for coding in c and even inserting the casual inline assembler function. in c# your are locked away from certain things, to protect you from certain common bugs attributed to certain techniques like dynamic memory management (you can still do it but the c# runtime environment will free the memory once it isn’t needed anymore, so you won’t forget to do that… this is called garbage collection).

opinions differ here as to what is the better way of learning programming. some people think that starting out with a lot of abstraction is good for focusing on algorithmic techniques first, without distracting you with language quirks. these people will tell you that you can always descend down to the system as you need to and will advise you to learn c at a later stage.

on the other end you will find those who believe that you need to start out with a very simple language syntax instead of abstraction. the arguement being that the closer you are to the machine when you start out the better you will understand how you computer really works, thus making you a better programmer.

both arguements have their merits and i’ve come to believe that it’s largely a matter of personal preference. some people might be comfotable with starting at the abstract end and others might enjoy really working with the machine, neglecting object oriented programming, etc. at first.

48d5487f357fbcacc89e84720577f0ac
0
Steven_Hansen 101 Jul 08, 2005 at 17:29

I largely concur with anubis, but want to add a couple cents.

In my experience, C# and C++ really have different uses. Microsoft wishes all C++ programmers would migrate to C#, but it isn’t going to happen for a while since each tool is suited to different tasks.

If I was asked to make a physics engine, or to work directly with opengl or directx, C++ is my preferred language - I really don’t want to mess with the overhead, hassle, and occassionally limited interaction provided by C# - at least not for big projects.

On the other hand, if I need a quick set of testing tools with GUI, C# is wonderful and chops the time it would take using C++ by well over 50%! The C# environment has some really friendly RAD tools (for building windows, dialogs, buttons, etc). For C++, you either have to code everything by hand (takes a while and requires win32 knowledge) or you have to use MFC (let’s hear a collective groan of dispair).

Your mileage may differ.

Aff64379e80eed342e80ba6fb92d340f
0
Kryogen 101 Jul 21, 2005 at 03:46

After doing some more research through my DirectX (June) SDK it appears that it is written in C++. Question then becomes, is there a C# version? It is a M$ product after all.

75c2c31bcca10ef21a86d5f5f49279d2
0
Tufty 101 Jul 21, 2005 at 05:08

It’s actually really easy to do DirectX stuff under C#. There’s quite a lot of tutorials out there. Just Google for it, I guarantee you’ll find something useful - but many developers still prefer to use C++ because there’s still a slight performance hit (which may or may not be offset by C# being faster to develop in).

F7a4a748ecf664f189bb704a660b3573
0
anubis 101 Jul 21, 2005 at 10:36

afaik the directx sdk includes a lot of code for c#. in fact all the tutorials should be available