Sunday, February 22, 2015

Pointers in c

What is a Pointer?

A pointer is a variable which contains the address in memory of another variable. We can have a pointer to any variable type.

The unary or monadic operator & gives the ``address of a variable''.
The indirection or dereference operator * gives the ``contents of an object pointed to by a pointer''.
To declare a pointer to a variable do:
   int *pointer;
 
1st example: x value is 1 and address is 100 
in ip we assign the address of x into ip.

2nd example: *ip means getting the value at the address
contained by ip . so ip has 100 and at that address it has value 1 
so that value is assigned to y.

3rd example: we assign the value of ip that is 100 to x so x now has 100.

4th example: now this is tricky so try to understand this carefully.
*ip means assigning the value at the address contained by ip (100)
so at the address assign value 3 .
now the memory address 100 the value is 3.
as x's address is 100 so now x value also is now 3. 


We can do integer arithmetic on a pointer:


   float *flp, *flq;
 
   *flp = *flp + 10;
 
   ++*flp;
 
   (*flp)++;
 
   flq = flp;
NOTE: A pointer to any variable type is an address in memory -- which is an integer address. A pointer is definitely NOT an integer.
The reason we associate a pointer to a data type is so that it knows how many bytes the data is stored in. When we increment a pointer we increase the pointer by one ``block'' memory.
So for a character pointer ++ch_ptr adds 1 byte to the address.
For an integer or float ++ip or ++flp adds 4 bytes to the address.
Consider a float variable (fl) and a pointer to a float (flp) as shown in 
 
Pointer Arithmetic Assume that flp points to fl then if we increment the pointer ( ++flp) it moves to the position shown 4 bytes on. If on the other hand we added 2 to the pointer then it moves 2 float positions i.e 8 bytes as shown in the Figure.



Pointers and Arrays

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) */
 
  Arrays and Pointers
To get somewhere in the array using a pointer we could do:

   pa + i $\equiv$ a[i] 



There is no bound checking of arrays and pointers so you can easily go beyond array memory and overwrite other things.

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] $\equiv$ a + i.  

We also express pointer addressing like this:

   pa[i] $\equiv$ *(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. 

Multidimensional arrays and pointers

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.


Consider int a[5][35] to be passed in a function:

We can do:

   f(int a[][35]) {.....}

or even:

   f(int (*a)[35]) {.....} 
These both are same.
 


We need parenthesis (*a) since [] have a higher precedence than *

So:

   int (*a)[35]; declares a pointer to an array of 35 ints.  

  int *a[35]; declares an array of 35 pointers to ints.  
Understand the above eg, carefully as this might be confusing.


 char Aname[10][20]; 
Aname has 200 elements.
access the elements via 
 20*row + col+bas+address
in memory

char *name[10];
name has 10 pointer elements.
each pointer element can point to arrays of different length.

Consider the below :



char *name[] = { ``no month'', ``jan'',
    ``feb'', ... };
   char Aname[][15] = { ``no month'', ``jan'',
    ``feb'', ... };
 
2D Arrays and Arrays of Pointers
 name points to array of 13 elements  which in turn hold reference (address ) 13 arrays.
no month\0 is one array that name[0] is pointing to.
similarly jan\0
(Notice Each string ends with '\0' . String is an array of char type )
Consider the below example:



What happens when we declare a one dimensional array in memory.
in A[5]
mem location:
    200   204  208  212 216

 -----------------------------------------
   |2  |  4  | 6  | 8  | 10 |
------------------------------------------- 
    ^     ^     ^   ^     ^
    |     |     |   |     |   
   A[0]  A[1] A[2] A[3]  A[4]

contiguous block of memory 
integer is stored in 4 bytes ( block of four bytes) 

int *p = A;
address of array A will stored in p so aestrick upon a variable is used to hold 
value of address.
now we can by using d-referencing  technique get other elements of the array A.
eg:
print( p ) // Will give address of Array A 1.e 200
print( *p ) // will print the value at 200 memory location i.e 2 
          // Above is what is called d-referencing a pointer using * with         //address will give us the value at that address
print(*(p+2) )// will print 6 . This addition of 2 to integer pointer variable   
              //means we will hop two times from starting aadress
              // in address if we add anything suppose 2 or 3 what it does is 
              //adds 2*(no of bytes occupied by one element) here 4 bytes
              // occupied by each int element so 2*4 = 8 
              // 200+8 is 208 so p+2 is 208 and *(p+2) is the value at
              //208 i.e 6/


C gives us the flexibility of using array name instead of pointer variable.
Remember: Name of the array returns the address to the first element in the array.
So print( p ) is same as print(A)
similarly 
*A will print the value at A i.e 2.
*(A+2) will give us 6.

*(A+i) is same as A[i] .( where i being any number in the range of array i.e 
                           0 to n , n being the length of array )
A+1 is same as &A[i] . both will give us the address of the i th element.

Imp thing to note is 

int *p;
we can do p = A;
but not 
A=p; //will give compilation error

 

Two dimensional array.
int B[2][3];
here we are creating arrays of array 
in this case we are creating 2 one dimensional array of length 3.
B[0] -- an array of 3 elements so will occupy 3* 4 bytes( 4 because 
        each int element will occupy 4 bytes each ) so 12 bytes tot
B[1] -- another array of 3 elements.

   400            412
 -----------------------------------------
    400    404   408
   |  2  |3  | 4 | 5 | 6 | 7  |
    ^
  B[0][0]
------------------------------------------- 
    ^              ^ 
    |              |
   B[0]            B[1]


 int *p = B // compilation error as B will return pointer to a 1D array.

int (*p)[3] =B ;// This now correct as p will be able to hold what B returns
               // that is pointer to a 1 D array of 3 elements.
 


print(B);     // same as &B[0] that is 400

print(*B);    // same as &B[0] or &B[0][0] 400

print(B+1);   // B returns array of 3 integers 
              // adding 1 to that is like 
              // hoping the 3 elements 
              // B is 400 add one is 
              // hoping 3 int elements
              // 4*3 =12
             //412
         /// Don't get confused as this is a 2d array 
        // remember as b returns array of 3 so adding one to B will 
           //let us hop 1st row and go to next row.

print( *(B+1)); // same as B[1] or &B[1][0] ,B+1 returns a pointer to the 
                //  1 d array of 3 elements as shown above so 412 

                // *(B+1) is similar to int *p = &B[1][0]

print (*(*B+1)) ; // *B is same as &B[0] as we see above 
                  // adding one to that is same as adding 1 to memory address 
                  // of &B[0][0] which will give 404 
                    // Now *(&B[0][0]) which is we are dereferencing address 404 
            /// it will give us 3.
print ( *(B+1)+2)    // same as &B[1][0] add 2 to it is 412 + 2*4 ( int elements 
                     // has 4 bytes == 420


Point to remember

for a 2-d array 
B[i][j] where i and j are some indices in the array is same as 

B[i][j] == *(B[i]+j)

B[i][j] == *(*(B+i)+j)

























courtesy: http://www.cs.cf.ac.uk/Dave/C/node10.html




 

1 comment:

Abby said...

Good tut....
Keep going on like this on other topics also....