Log in using your OpenID or your Sol Union log in account.
[Cancel]     

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);
}