Our Sites:  Tutorial Buzz  |  How To Tree  |  Recipe Voice  |  Golf Twist  |  DIY Click  |  Movie Lizard  |  Halloween Twist  
Search:
Submit Link
Mail to a Friend
RSS FeedReceive updates via our RSS feed

Pointers and References in C++

Introduction
The ability to manipulate memory and memory locations directly is part of what makes C and C++ so powerful, so dangerous, and so difficult for beginners. C only has "pointers", but C++ uses pointers and "references" that have a nicer syntax and attempt to be safer. This article will attempt to demystify these concepts in the minds of beginning C/C++ programmers.

This article assumes the reader has a basic understanding of C/C++ including variable declaration, conditionals, loops, functions, and data types. This article will speak more specifically about C++.

Remember, pointers can twist your mind at first and they are a difficult concept to grasp. Often times it is hard to see where they would be useful.

The Basics
The "normal" way of storing information (data) in C++ is using certain predefined types like integers (int), floating point values (float, double), and characters (char). The programmer tells the compiler about the data he wishes to store by giving its type, its name, and possibly an initial value.

int total_balls = 2300;
float gravity = 9.8f;
char start_char = 'a';

None of this should be new or difficult. This is easy, assuming you know the different types, and the best part about it is that the compiler takes care of finding a place to store the variable and we just tell it when we want to know what is "stored" in the variable. But wait! The compiler knows where the variable is stored in memory, it has to. We can get at the address of a variable by using the address of operator, "&" (ampersand).

std::cout << &total_balls;
std::cout << &gravity;
std::cout << &start_char;

But why would we care about knowing the address of our variables? The compiler takes care of storing our data for us, right? Yes, and we as humans have very little use of printing out the addresses of variables except for debugging purposes. But we can store an address of a variable into a special data type called a pointer and the compiler takes care of storing our "pointer value" for us. We designate pointers with a data type (int, float...) followed by the * (asterisk) symbol.

int* addr_balls = &total_balls;
float* addr_grav = &gravity;
char* addr_char = &start_char;

Now we have variables that store the addresses of the other variables we already created! Not very useful yet. But these concepts are important, a pointer can point to practically anywhere in the computers memory, and wherever it is pointing to we can retrieve the value there or store a new value in that location.

Most pointers have a type associated with them, but there is a special pointer, a red-head in the group, called a void pointer (void*). Well, what's at the other end of the pointer, what is stored in the location? The programmer has to know that and cast it into an appropriate type.

Dereferencing and Multiple Pointers
If we have the address of an integer how do we get at the integer instead of the address. We use the * (asterisk) symbol again, which can be somewhat confusing.

// Declare an integer.
int total_balls = 205;
// Declare a pointer that "points" at the address of total_balls.
int* addr_balls = &total_balls;
// Print the address of total_balls twice.
std::cout << &total_balls << " " << addr_balls;
// Print out the value of total_balls twice.
std::cout << total_balls << " " << *addr_balls;

In this way we can switch between the memory address and the actual value stored there effortlessly. We can also have a pointer to another pointer, which requires two * (dereference) to obtain the object.

int a = 0;
int b = 1;
int* addr_int = &a;
int** addr_addr_int = &addr_int;
**addr_addr_int = 3; // changes variable "a" to 3
addr_int = &b;
**addr_addr_int = 3; // WOW, the same exact line now changes variable "b"

Practical Pointers
So far, we haven't really seen the use of pointers. Why do we need to know the address of a variable? There are many reasons including storing contiguous data (arrays), storing a "string" of characters (string), taking over memory management from the compiler, manipulating the same data from different functions, and not duplicating large chunks of memory when passing to a function in order to increase performance. Don't worry if these sound confusing now

Pointer Arithmetic
An array is a bunch of variables stored one after the other in memory so we can easily access any of the variables with a number. Instead of saying "Give me the book by Thomas Hardy" we can say "Give me book #3."

If we have a pointer to the first variable in an array, we can get or set the value of any other variable in the array. Since we know how big each object is we can "jump" to the correct address with some simple multiplication and addition. You've probably seen array[5] to get the sixth element in an array (remember array[0] is the first element). To calculate that location we move over 5 elements. Then we dereference that spot, to work with the object there. So array[5] == *(array + 5) is true. Notice how we dereferenced the address after we moved over five elements.

In fact it is hard to give a short example showing the usefulness of pointers since they mostly crop up in larger projects. But a character string is a good way to start.

// Something probably familiar:
char message[] = "Hello";
// But it's really sugary syntax for:
char message[] = {'H','e','l','l','o','\0'};

We have a pointer to a character and we know that after that character is another character, and after that another character until we reach the value 0. So we can print out a word, instead of just a character!

int index = 0;
while( *(message + index) != 0 )
{
   std::cout << *(message + index);
   ++index;
}
// alternatively
while( message[index] )
{
   std::cout << message[index];
   ++index;
}
// or simply
std::cout << message;

In that last example, the program doesn't do what you might expect it to do. It should print out a char* but instead, when you insert a char* into a output stream, it steps over every character until it reaches the null character (0) or ("\0").

About this Tutorial
This tutorial is from The Game Progamming Wiki which is published under the GNU Free Documentation License 1.2.

InfoWorld's Java IDE Comparison Strategy Guide
If you're looking for a Java IDE, you want one based on Eclipse. But which offering do you want? Download the Infoworld Java IDE Comparison Strategy Guide. In this three-part guide we'll go deep into the details, comparing Technology of the Year winner JBuilder 2007, IBM's IRAD, MyEclipse and the free open-source Eclipse platform.

We close this Java IDE Strategy Guide with a look at an advanced concept in Java development: Application Factories. This innovative development metaphor and associated collection of tools allows developers to focus more on the nature and purpose of the application, and less on the underlying platform, framework, and technologies being used.

Request Your Free Strategy Guide!

Home  |  News  |  Source Code  |  Tutorials  |  Components  |  Tools  |  Books  |  Free Magazines  |  Jobs  |  Gear  |  Hosting  |  Links
 
Copyright © 2000 - 2006 Code Beach  |    |  Privacy Policy
 
Free thumbnail preview by Thumbshots.org