|
|
 |
|
 |
|
|
C++ Language Tutorial Page 8
Arrays and Pointers
Ned Bingham
Previous Index Next
Pointers
A pointer is a variable that stores the address of another variable instead of data.
Pointers are extremely useful, as you can pass huge amounts of data without lag-time. You can also have
instant access to variables between classes without a mess of update functions or a class hierarchy, or
have something called dynamic variables.
Pointers are essentially a direct access to the computers virtual memory.
The memory in a computer can be visualized as a number line in hexadecimal. For example, the address
0xFEEDFACE is just the number 4277009102 in hexadecimal format. Hexadecimal is a base 16 number
system. The letters actually represent numbers in hexadecimal because there aren't enough one digit numbers
to use. So, A is 10, B is 11, and so on until F, which is 15. Just like in base ten, where the number 25 is
5*10^0 + 2*10^1 + 0*10^2 + ..., in base 16, the number 1E is 14*16^0 + 1*16^1 + 0*16^2 + ..., which evaluates
to 30 in base ten. In a 32 bit operating system, an address in memory is always 32 bits, which is 32 binary
digits or 8 hexadecimal digits. In a 64 bit operating system, an address is always 64 bits, which is 64 binary
digits or 16 hexadecimal digits. In C++, a 0x in front of a hexadecimal number tell the compiler that it is a
hexadecimal number and not some rubbish. Hence 0xFEEDFACE and not FEEDFACE.
DISCLAIMER
Obviously, since you are working almost directly with the computer's memory, pointers
are a little dangerous. So take caution: if you define an array or a dynamic variable and don't release it,
then you will experience what is called a memory leak. The unreleased memory remains after the program has been
shut down, taking up space. This prevents any other applications from using it, including the operating system.
This is bad.... BAD. If this does happen, it will manifest itself as the computer slowing down, and
you should restart the computer immediately. Restarting the computer clears the computer's ram so it can
be used again. Then, go and try to fix the memory leak, restarting in between each run. Memory leaks can cause a lot
of damage to your operating system. For example, I have completely corrupted my system and lost all of my work before.
I am not responsible for any damage that you cause to anyone's computer.

xkcd.com
Now that I have scared the crap out of you, we can continue with pointers. Pointers are just like integer variables,
only you can easily access the data at the number they store along with the number they store. Here is how to declare a
pointer:
variable_type *name;
Setting the address of a pointer is just like setting the value of an integer.
name = address;
Then, to access the value at that address, you use the unary operator (*). When using the unary
operator, the binary data stored at that address is interpreted as the variable type specified when you declare the pointer.
int *name;
name = 0xBEEFFACE;
cout << name << "\n";
cout << *name;
The above code will probably display some random rubbish of a number that has absolutely no significant
meaning to you, so how do you safely use it? Well, make another variable. To get the address of a variable, you use the
binary and operator (&).
int var1 = 25;
int *pvar1 = &var1;
cout << pvar1 << "\n";
cout << *pvar1 << "\n";
*pvar1 = 6;
cout << var1;
Pointers to classes, structures, and unions work exactly the way normal pointers do,
except that instead of using the dot operator (.) to access class variables, you use the pointer operator (->).
You don't have to point a pointer to an existing variable, you can also dynamically
allocate a variable. This is the beginning of the dangerous part. If you dynamically allocate a variable,
then you also have to dynamically deallocate a variable. (allocate as in allocate space in memory for a
variable) To do this in C++, you use the new and delete operators.
int *pvar;
pvar = new int;
// use pvar as you would a normal pointer
delete pvar;
Once again, you have to delete the dynamic variable after you are done using it and
before the program shuts down or you will have a memory leak.
Arrays
Arrays are simply matrices of a variable type. They can be of any dimension, 1, 2, 3, 4,
ect. Visualizing arrays is quite a simple task for lower dimensions, but once higher dimensions come in to
play it becomes a little more difficult. Here is how to visualize arrays filled with zeros:
One dimensional array of 10 spaces:
index 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
array [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Two dimensional array of 10 by 10 spaces:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
3 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
4 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
5 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
6 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
7 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
8 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
9 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
The size of the array is specified when the array is declared, then the index is
used to point to a specific element in the array.
variable_type name[size 1][size 2][...][size n-1][size n];
To access an element in an array, its the same syntax, except instead of putting
the size in the brackets, you put the index along that dimension in the brackets.
int arr[10][10];
for (int x = 0; x < 10; x++)
for (int y = 0; y < 10; y++)
arr[x][y] = x*y;
cout << arr[5][3] << "\n";
In this case, the output should be the value of the array at index 5, 3
which is equal to 15. Like normal variables, arrays can also be dynamically allocated. This is
where pointers get extremely dangerous, because you are allocating large swaths of memory at once.
When you dynamically allocate arrays, the pointer points to the first element in the array, and you
don't have to use any of the special unary of binary and operators with arrays, because using the
array brackets (name[index]) automatically turns the address into the value at that address. Once
again, you use the new and delete keywords, but there is a little difference. Here is how to
dynamically allocate an array.
int *arr;
// notice the [10] after the new int.
arr = new int[10];
// use arr just like you would normally use an array.
for (int x = 0; x < 10; x++)
arr[x] = x;
// notice the [] after delete.
delete [] arr;
The brackets after the new int declares the size of the one dimensional array,
and the brackets after the delete tell the compiler that it is deleting an array of variables instead
of just one. Other than using new and delete, the dynamic array is used just like a regular array.
dynamic arrays are useful because you can declare them in a class before you know the size they have
to be, and just decide the size later. You can also resize the array if you need more space, just
create a pointer and declare a new bigger array, copy the data over to the new array and and set the
pointer to the original array to point to the new one. To get the address of an array, you just use
the name of the array, you don't need to use brackets, unary, or the binary and operators.
To include arrays or pointers into functions as input, you simply just import the
address of the pointer. Here is an example
void func(int *ptr, int *arr, int arrsize)
{
cout << *ptr << " " << ptr << "\n";
for (int x = 0; x < arrsize; x++)
cout << arr[x] << " " << &(arr[x]) << "\n";
}
void main()
{
int arr[10];
int b = 0;
for (int x = 0; x < 10; x++)
arr[x] = x;
func(&b, arr, 10);
}
|
|
|
|
|
|