C Language Reference for Script Programmers - Pointers
what are they?
the value of a pointer is a hex
how big are they?
what makes them so
passing by value
passing by reference
By passing the address of a variable (passing a pointer) we are “passing by reference” rather than by value. By reference we mean address. This can be viewed as a disadvantage in that you need to take extra precautions if you don’t want the data that is passed by reference to be altered from within the function. However since C limits functions to returning only a single value this is the only way to trick a function into returning more than one value. We can pass the address of several variables and alter all of the them within the function, getting around the single return value.
If you haven’t absorbed all that yet don’t worry about it. We’ll go back over all of it now with some examples. But keep in mind that the biggest cause of bugs is misuse of pointers, so even the pros have a hard time with them from time to time. So don’t get discouraged.
int * pint;
this creates a pointer to an int, a pointer to a char and a pointer to a double respectively. Adding a ‘p’ to the beginning of the variable’s name helps us remember that it is a pointer, but is not required. The * after the typename in a declaration means that it is a pointer, the * has many other meanings that depend on the context as we will soon see.
int * pint;
Here we declare two variables, a pointer to an int and an int. Then we assign the address of the int to the pointer. The last line is read “pint equals the address of a_real_int”. So the value of pint is the address of a_real_int, which might look something like: 0x00000143 (the 0x prefix indicates that this is a hex number, in base 10 it would be: 323).
It should be fairly obvious that a pointer can have it’s value changed just like any other variable. That means that a pointer need not always point to the same variable, this can be very useful. Also just as three ints can all have a value of 25, three pointers can all have a value of 0x00000008. That is more than one pointer can point to the same variable.
pint = 35;
thinking that this will change the value of a_real_int to 35. This is not the case however, the line above will change the value of pint (which we remember is an address) to 35 or 0x00000023. That can have catastrophic results since pint will be pointing to the memory stored at address 0x00000023 which could be anything, some other program’s data or worse yet system information.
Clearly we need some way of identifying when we intend to change the value (address pointed to) of a pointer, and when we intend to change the value of the variable pointed to by the pointer. We do so with the help of our old friend the asterisk:
*pint = 35;
Yup that’s the same * we used to declare the variable as a pointer, now we’re using it to indicate that we want to access the variable pointed to by the pointer. Don’t worry if you think that seems weird, it is. As I said earlier the * has several meanings that all depend on context. In a declaration it means that the variable is a pointer. Anywhere else it indicates that the variable that follows is to be “dereferenced”. By dereferenced we mean that we want to access the variable that the pointer references (or points to). Of course * also means multiply so you need to be careful to observe the order of operations (see a C book). When in doubt surround the variable with parentheses and you’ll be fine:
a_real_int = 25 * (*pint);
The line above assigns to a_real_int the value of 25 times the value of the int that pint points to. According to our example pint points to a_real_int so the line above makes a_real_int equal 25 times it’s previous value.
passing as arguments
*val1, int *val2)
This function takes two arguments both of type pointer to int. The code of the function takes the value of the int pointed to by the second argument and assigns it to the value of the int pointed to by the first. We would call the function as follows:
// assign the addresses of the ints to the
// use pint2 to set the value of number2 to 56:
// call the function test_func( ) to assign the value
You’ll notice that when we pass pint1 and pint2 to test_func we don’t use a *. The reason for this is that the function is defined as taking int *’s as it’s arguments, and both pint1 and pint2 are int *’s, therefore no dereferencing is necessary. If we had dereferenced them as in:
we would be attempting to pass ints, not int *’s. This would result in a compile time error, so don’t do that.
Here’s something that might not be immediately obvious but should help you understand pointers better:
number2 = 56;
test_func( &number1, &number2);
Can you see why this works? Remember that a pointer’s value is an address. What are we passing to the function test_func in this example? We’re using the address operator to pass the address of number1 and number2. Remember also that C passes by value, that is the variables val1 and val2 of test_func get the value of the arguments passed to the function assigned to them. Since the values being passed are addresses, and the value of pointers are addresses, they are compatible. The value of an address to an int is the same as the value of a pointer to an int (because they are the same thing), a hexadecimal address.
|Converted from CHM to HTML with chm2web Pro 2.82 (unicode)|