Introduction
The Pointer is probably a most useful and smart thing that came along with the C language. Those who don�t realize this has no idea of what coding means (I always have the definition: �to Code� = �programming in C or C++ language�). The Pointer is a very powerful tool and can be used in various ways. More about this you�ll find out in this material.
Premises
I will begin with the most common and known definition: A Pointer is a type-variable in which is stored the memory address of an object. This means that the value contained in this variable is an address. Now, don�t think of those commonly used hexadecimal values, like 0x440562 that you have seen in various open-sources.
Let�s say that the third value, 156, is the value of a variable Var
. So, we have:
int Var;
Var = 156;
The value of Var
is stored at the address 102. Now, we�ll declare a pointer:
int *pVar;
The following step is to assign a �value� to this pointer. If we assume that we know the memory address where the value of Var
is stored then we can do:
pVar = 102;
This is not at all recommended, because in most of the cases you don�t know the address. A code line like the one above, will give you a message of �Segmentation fault�, if you compile it and run it under Unix-like systems. What you can do is:
pVar = &Var;
The translation of the symbol �&
� is �address of�. So, this means that pVar
= address of Var
. Now, in the pVar
variable we have the value 102. We can say now that �pVar
points to Var
�, which means that the address of Var
is contained in the pVar
variable. The next step is to access the value stored at the address pointed to by pVar
. We do this by using the �*
� symbol:
int NewVar;
NewVar = *pVar;
Now, we have assigned the value contained at the address pointed to by pVar
to the NewVar
variable. So, the translation of �*
� is �value at the address�. The output of:
printf( "value of NewVar = %d", NewVar );
will be:
value of NewVar = 156
Also, you can assign a value to the Var
variable by using the pVar
pointer. That�s because the address in which Var
is stored will not change and the pVar
is pointing at that address:
*pVar = 173;
So, �the value at address� pVar
is now 173 and the memory will look like this:
Types of pointers
There are different types of pointers. As I said before, a pointer is a variable that contains a memory address. But the value stored at that memory address can be of a specific type, like double
, int
or char
. That�s why there are different types of pointers.
int SomeVar;
int *pSV;
pSV = &SomeVar;
In the example above, we have assigned to pSV
the address of SomeVar
. To be able to do this (and not to get a nasty error message or warning � depending on the compiler), we have to declare: int *pSV
, which means that pSV
will point to a value of type int
.
Never try to do something like:
float AnotherVar;
long *pAV;
pAV = &AnotherVar;
This means that in pAV
you are about to store the address of a float
variable. But pAV
type is long
, and the ANSI standard tells us that something like this is not possible.
Operations with pointers
There are two categories of operations:
- Pointer operations.
- Operations with the values pointed by pointers.
The last category is already known, because those are same like the ones with normal variables:
double AVar;
double BVar;
double *pA;
double *pB;
AVar = 20;
BVar = 12;
pA = &AVar;
pB = &BVar;
(*pA)++;
(*pB)--;
(*pA) -= (*pB);
printf( "value of AVar = %lf\n", *pA );
printf( "value of BVar = %lf\n", *pB );
The output will be:
value of AVar = 10
value of BVar = 11
Now, let�s see what operation we can do with the pointers, or better said, with the addresses stored in the pointers. But, before we start, we have to define the �address� word. To define it, we need to know the representation of memory and how the operating system works with it.
The memory can be �seen� as an array of bytes (1 byte = 8 bits). That�s for almost all of the computers, and this representation is related to physical, economical restrictions and practical reasons. The dimension of this array is equal to the amount of physical memory your computer may have. This doesn�t mean only the RAM that you install on it, but there is some extra memory to add here, like video ones and swap. So, the memory is an array of bytes and its elements can be accessed specifying an index. This index is called address. And here comes the first restriction:
You cannot assign to a pointer a negative value (look at the value as an address, not the value contained at that address). That's because the memory starts at 0 and ends at whatever your computer may have.
But this one is not the only restriction. Because the memory is being used, also by other processes (applications or OS managing operations), you cannot assign random values to the pointer, because you�ll probably crush the system (MS-DOS, Win 95, �98, ME) or your application will get crushed (Unix-like systems and WinNT-based).
int *pC;
pC = 15;
(*pC) = 200;
So, it�s better to let the system to manage the memory. You just work with it.
Now, we can get back to what this topic is all about: operations with pointers. There are not much: four of them: �+
�, �++
�, �-
�, �--
�. You can add two pointers, increment a pointer, subtract a pointer from another one, decrement a pointer. For a better understanding, let�s take an example:
float A;
float B;
float C;
float *pA;
float *pB;
float *pC;
A = 100;
B = 150;
C = 14;
pA = &A;
pB = &B;
pC = &C;
pC = pA + pB;
pC++;
pA = pA - pB;
pB--;
- Here we add two pointers,
pA
and pB
, and the result goes to pC
. This means that we are adding the address contained by the pointer pA
with the address contained in pB
, and the result is stored in pC
. This is a pretty dangerous thing to do, if you don�t know anything about the resulting address. This is just for example and you have to understand that an operation like this one is allowed, but you have to know how to use it in safe conditions.
- We can increment a pointer. The following explanations apply to the 4th case, too. When we�re incrementing an address, we have to be aware of the pointer�s type. In the case of a
char
type pointer � a char
variable is stored in 1 byte. So, a char
pointer will point to a char
value. If we are incrementing the pointer, then it�ll point to the next char
value. This means that if the address contained in the pointer is, let�s say, 100; and we�re incrementing it, the new value will be 101. This is not the same thing for a long
or float
type pointer. For most operating systems (Unix-like and Windows suite), variables of long
and float
type are stored using 4 bytes. Now, let�s say we have a float
pointer = 100. If we�re incrementing it then the new value will be 104. It is very important for you to understand this, before you start using pointers in your applications. Also, when you use pointers, maybe you�d like to know what is the amount of bytes used to store a variable of a specific type. You can find out this with the sizeof()
function.
- In this case, the rules are the same like for case 1. In addition, you�ll have to be careful no to get a negative value for the address. This means that the value of the pointer from which we are subtracting is not to be smaller than the value of the pointer subtracted.
- Like I have said before, the rules from case 2 apply in this case, too. Additionally, we have to check out if the pointer will be negative after decrementing it. If so, the operation is not allowed. Also, the address is an integer value and you cannot make operations like adding to or subtracting from a pointer a non-integer value, like in the following example:
double *pD;
pD = pD - 100.32;
Be aware that the pointer is double
. That doesn�t mean that the address is double
. This means the value contained at that address is double
.
Independent pointers
That�s not a correct term, but I have considered it appropriate to be used in this case. In all the above topics, I explained only the cases in which we are assigning to the pointer the address of an already defined variable. But what can we do with pointers when we do not assign any address? How can they be used?
As I said before a pointer value is an address. That address can be an existing one, like the address of an already defined variable. You, also, allocate memory to it and work with the pointer. This means that you�ll not have to assign an address to it anymore� but allocate to it an address of its own. This way you�ll work with the pointer as it is and not define any unnecessary variable:
int *pVar;
pVar = (int*)malloc( sizeof(int) );
*pVar = 56;
By saying �allocating memory�, you have to understand that the system will make some space, somewhere in the memory, for the pointer, and will automatically assign the address of that location to the pointer. The malloc()
function makes all this. If some problem occurs during this operation then the address assigned to the pointer will be NULL
, which means no address. You can check this using the following method:
pVar = (int*)malloc( sizeof(int) );
if( NULL == pVar )
return <some error>;
*pVar = 56;
� and with this, you are prepared for the next topic:
Pointers to arrays
In C language, there is an enclose relation between pointer and array, these two entities being almost interchangeable. This relation is probably a most powerful and unique tool. When you use an array without index, you are in fact generating a pointer to the first element in the array, so the compiler will actually take everything till it encounters the first NULL
:
char szMessage[] = "this manual is great!";
printf( "%s\n", message );
In the example above, I have passed to printf()
an array of char
s. The function takes the address of the first element, this by converting it to a char
pointer. That�s because in C language it is impossible to pass to a function an array. You are only passing the address of the first element of it. Even if you weren�t aware of it, you already have used pointers. Because the name of an array without an index represents the address of the first element, you can assign this address to a pointer and you�ll have access through it, to any element in the array. These kind of pointers are named arithmetic pointers.
int Array[ 6 ] = { 1, 2, 3, 12, 54, 5 };
int *pArray;
int i;
pArray = Array;
for( i = 0; i < 6; i++ )
printf( "%d\n", Array[ i ] );
for( i = 0; i < 6; i++ )
printf( "%d\n", *(pArray + i) );
Pointers to structures
A commonly used C technique is to access a structure via a pointer. Declaring a pointer to a structure is done in the same way as for any other data-type described above.
struct SomeStruct
{
int AVar;
double BVar;
} AStruct, *pAStruct;
AStruct
is a variable of type struct SomeStruct
and pAStruct
is a pointer to a structure of this type. So, now we are allowed to assign to pAStruct
the address of the variable AStruct
.
pAStruct = &AStruct;
To access the members of the structure using the pointer, we will have to use the arrow operator �->
�.
pAStruct->AVar = 12;
This means that we have assigned the value �12� to the AVar
member of the structure AStruct
, using the pAStruct
pointer. Like the use of all the other kind of pointers I have described above, this one is very important, too. Let�s say you�re passing a structure, as a parameter, to a function. What the C compiler does is this: transfers the entire structure to the function that is being called. When we have very large structures, like the ones you can see in the WinAPI, there can be a very large loss of memory and processing time. Here comes the use of pointers to structures. If you will pass that structure to the function by using a pointer to it, the compiler will then only transfer the address of the structure. In very complex applications, this kind of techniques are vital.
Conclusions
A wise man has once said that �we are jumping to conclusions when we are bored of thinking�. The C language has become one of the most powerful non-Object-Oriented languages just because of the pointers. They offer you low-level access to the memory resources and a lot of speed in complex applications. I hope this material made you understand the power of pointers. If you will use them correctly at least once, I am sure that you�ll see why I am such a big fan of them.
Points of Interest
Well... if you had no idea what a pointer is, then, hopefully, you've learned from this material.
History
- Version 1.0 - 23 February 2005 - This material was posted three years ago on a different site. But that community does not have too much activity, so I don't like them anymore :).