| Pointers are a fundamental part of C. If you cannot use pointers properly then you have basically lost all the power and flexibility that C allows. The secret of C is in its use of pointers. |
| C uses pointers a lot. Why? |
| It is the only way to express some computations. |
| It produces compact and efficient code. |
| It provides a very powerful tool. |
| C uses pointers explicitly with following: |
| 1. Functions. |
| 2. Arrays. |
| 3. Structures. (discussed later) |
| Note: Pointers are perhaps the most difficult part of C to understand. C's implementation is slightly different from other languages. |
| What is a Pointer? |
| A pointer is a variable which can hold the address of a memory location rather than the value at the location. |
| Pointer Notation |
| The actual address of a variable is not known immediately. We can determine the address of the variable using address of operator(&). |
| We have already seen the use of address of operator in the scanf() function. |
| Another pointer operator available in C is "*" called "value of address" operator. It gives the value stored at a particular address. This operator is also known as indirection operator. |
| Pointer Declaration |
| To declare a pointer to a variable: |
| int *pointer; |
| Note: We must associate a pointer to a particular type: You can't assign the address of a short int to a long int, |
Donate
| Like other variables pointer variable can also be used in expressions. Arithmetic and comparison operation can be performed on the pointers. |
| Pointer Arithmetic |
| Example: |
| Addition of a number to a pointer int i=4,*j,* |
| j=&i; |
| j=j+1; |
| j=j+9; |
| k=j+3; |
| Example: |
| Subtraction of number from a pointer int i=4,*j,*k; |
| j=&i; |
| j=j-2; |
| j=j-5; |
| k=j-6; |
| But the following operation are not allowed on pointers: |
| a) multiplication of pointer with a constant |
| b) addition of two pointer |
| c) division of pointer with a constant |
| Pointer Comparison |
| Pointer can be compared using relational operator. Expression such as- p1>p2 p1=p2 p1!=p2 are allowed. |
Let us now examine the close relationship between pointers and C's other major parts. We will start with functions.
When C passes arguments to functions it passes them by value.
There are many cases when we may want to alter a passed argument in the function and receive the new value back once the function has finished.
C uses pointers explicitly to do this.
The best way to study this is to look at an example where we must be able to receive changed parameters. Let us try and write a function to swap variables around?
The usual function call:
swap (a, b) won't work.
Pointers provide the solution: Pass the address of the variables to the functions and access address of function.
Thus our function call in our program would look like this:
swap (&a, &b)
The Code to swap is fairly straightforward:
void swap(int *px, int *py)
{ int temp;
temp = *px;
/* contents of pointer */
*px = *py;
*py = temp;
}
Hint: Think of array elements arranged in consecutive memory locations.
Consider the following:
int a[10], x;
int *pa;
pa = &a[0]; /* pa pointer to address of a[0] */
x = *pa;
/* x = contents of pa (a[0] in this case) */
Warning: There is no bound checking of arrays and pointers so you can easily go beyond array memory and overwrite other things.
C however is much more subtle in its link between arrays and pointers.
For example we can just type:
pa = a;
instead of
pa = &a[0]
and
a[i] can be written as *(a + i).
i.e. &a[i] =a + i.
We also express pointer addressing like this:
pa[i] =*(pa + i).
However pointers and arrays are different:
A pointer is a variable. We can do pa = a and pa++.
An Array is not a variable. a = pa and a++ ARE ILLEGAL
This stuff is very important. Make sure you understand it. We will see a lot more of this. We can now understand how arrays are passed to functions.
When an array is passed to a function what is actually passed is its initial element location in memory
So: strlen(s) strlen(&s[0])
This is why we declare the function:
int strlen(char s[]);
An equivalent declaration is:
int strlen(char *s);
since char s[] is equivalent to char *s.
strlen () is a standard library function that returns the length of a string.
Let's look at how we may write a function:
int strlength(char *s)
{
char *p = s;
while (*p != '\0');
p++;
return p-s;
}
Now let’s write a function to copy a string to another string. strcpy () is a standard library function that does this:
void strcopy (char *s, char *t)
{ while ( (*s++ = *t++) != `\0' );}
This uses pointers and assignment by value.
Note: Uses of Null statements with while.
Malloc Library Function
Function: Allocates main memory
Syntax: void*malloc(size_t size);
Prototype in: stdlib.h, alloc.h
Remarks: malloc allocates a block of size bytes from the C heap memory. It allows a program to allocate memory explicitly, as it is needed and in the exact amounts needed.
Calloc Library Function
Function: Allocates main memory
Syntax: void*calloc(size_t n size);
Prototype in: stdlib.h, alloc.h
Remarks: Calloc provides access to the C heap memory . Calloc allocates a block of size n items of x size. The block is cleared to 0.
| We should think of multidimensional arrays in a different way in C: |
| A 2D array is really a 1D array, each of whose elements is itself an array |
| Hence |
| a[n][m] notation. |
| Array elements are stored row by row. |
| When we pass a 2D array to a function we must specify the number of columns and the number of rows is irrelevant. |
| The reason for this is pointers again. C needs to know how many columns in order that it can jump from row to row in memory. |
| Considerint a[5][35] to be passed in a function: |
| We can do: |
| f(int a[][35]) {.....} |
| or even: |
| f(int (*a)[35]) {.....} |
| We need parenthesis (*a) since [] have a higher precedence than * |
| So: |
| int (*a)[35]; /*declares a pointer to an array of 35 int */ |
| int *a[35]; /*declares an array of 35 pointers to int */ |
| Now lets look at the (subtle) difference between pointers and arrays. Strings are a common application of this. |
| Consider: |
| char *name[10]; |
| char Aname[10][20]; |
| We can legally do name[3][4] and Aname[3][4] in C. |