Wednesday 8 October 2014

More on C pointers

Initialize a pointer

Before you can use a pointer in for instance a printf statement, you have to initialize the pointer.
The following example will not initialize the pointer:


 #include<stdio.h>

 int main(void) {
  int *ptr_p;
  printf("%d\n",*ptr_p);
                return 0;
 }


In this example we print the value that ptr_p points to. However, we did not initialize the pointer. In this case the pointer contains a random address or 0.
The result of this program is a segmentation fault, some other run-time error or the random address is printed.
The meaning of a segmentation fault is that you have used a pointer that points to an invalid address. In most cases, a pointer that is not initialized or a wrong pointer address is the cause of segmentation faults. The next example demonstrates the correct usage of pointers:


 #include<stdio.h>

 int main(void) {
  int x;
  int *ptr_p;
  x = 5;
                ptr_p = &x;
  printf("%d\n", *ptr_p);
                return 0;
 }

Note: If you forget to place * (in front of the pointer) in the printf statement, you will print the address of integer x. (Try it!).

Pointers as function arguments

The C language is a “call by value” language, which means that the called function is given a copy of its arguments, and doesn’t know their addresses. (For example myfunction(x) call is given, the value of x is passed, not its address). This makes it impossible to change the value of x from the inside of the function (myfunction).
Note: With an array this is not a problem. If x is an array (char x[10]) then x is is an address anyway.
Take a look at the following example, which will illustrate the problem:


 #include<stdio.h>

 void swapping(int c, int d) {
  int tmp;
  tmp = c;
  c = d;
  d = tmp;
  printf("In function: %d %d\n", c , d);
 }

 int main(void) {
  int a,b;

  a=5;
  b=10;
  printf("input: %d %d\n", a, b);
  swapping(a,b);
  printf("output: %d %d\n", a, b);
                return 0;
 }

In the example the values of the parameters are swapped in the function swapping. But when the function returns nothing will happen. The result is that the values are not swapped. (Try it!).
Pointers can be used to get around the “call by value” restriction. In the next example we will use pointers to correct the problem:


 #include<stdio.h>

 void swapping(int *ptr_c, int *ptr_d) {
  int tmp;

  tmp = *ptr_c;
  *ptr_c = *ptr_d;
  *ptr_d = tmp;
  printf("In function: %d %d\n", *ptr_c , *ptr_d);
 }

 int main(void) {
  int a,b;

  a=5;
  b=10;
  printf("input: %d %d\n", a, b);
  swapping(&a,&b);
  printf("output: %d %d\n", a, b);
                return 0;
 }

Note: Don’t forget to replace “swapping(a,b);” for swapping(&a,&b);”.

Pointing to the same address

There is no limit on the number of pointers that can point to the same address.


 #include<stdio.h>

 int main() {
  int a;
  int *ptr_b , *ptr_c, *ptr_d;

  ptr_b = &a;
  ptr_c = &a;
  ptr_d = ptr_b;
  return 0;
 }

Note: The variable a now had four names: a, *ptr_b, *ptr_c and *ptr_d .

Pointers and arrays

The C language allows pointer addition and subtraction. Let’s take a look at this example:
char array[10];

char *ptr_toarray = &array[0];

In this example we declare an array with ten elements. Then we declare that the pointer *ptr_toarray is the same as array[0] (the same as the first element of the array). Now we could do the following (note the placing of the parentheses):

*(ptr_toarray + 2);

This is the same as array[2]. So you can see, the C language allows arithmetic’s. But remember to place the parentheses very carefully. ( *(ptr_toarray + 2); is something different then *(ptr_toarray) + 2; ).

Pointers and common errors

In this paragraph we will talk about some common errors that can occur with pointers.
1) Pointers that are not initialized
If a pointer is not initialized, a pointer will point to a random memory location. For example:

     int *A;
     *A = 5;

When we declare pointer A, it will point to a random memory address. The pointer could point to memory of program code space, system stack etc, etc. (We don’t know). Then we say *A = 5; the program will try to write the value five at the random location A is pointing to. The program may crash right away, run for an hour and crash, corrupt data or nothing will happen. The result cannot be predicted. So always initialize pointers.
2) Invalid pointer reference
We have two pointers, A and B. A is initialized and B is not. If we say “A=B;”, pointer A points
to a random memory address (remember B is not initialized). Now any reference to *p is now an invalid pointer reference.
3) NULL pointers: run-time error and segmentation fault 
The NULL pointer has a reserved value in the C and C++ language (very often the value zero but not necessarily). It indicates that it refers to nothing. A NULL pointer should not be confused with an uninitialized pointer. Because it refers to nothing, an attempt to dereference a NULL pointer can cause a run-time error (or often in C programs a segmentation fault).
That’s all for this tutorial.

No comments:

Post a Comment