Monday, January 16, 2012

Array Parameters are ALWAYS Pointers

 Array Parameters are always Pointers 

There is no way to pass an array to a function directly. 
Using an array name as an argument immediately converts it to a 
pointer to the initial element of the .array.For example, writing:


char hello[]= "hella"; declares hello as an array of characters.
Passing that array to a function: printf ("%s\n" , hello); is 
precisely equivalent to passing the address of its initial 
character: printf("%~'b", &hello[O]); Thus it is never meaningful
to use an array as a function parameter.For this reason, C 
automatically converts an array parameter declaration to the 
corresponding pointer declaration.

The following two definitions of foo()look different, 
but to the compiler they mean exactly the same thing. It’s 
preferable to use whichever syntax is more accurate for 
readability.If the pointer coming in really is the base address 
of a whole array,then we should use [ ].
void foo(int arr_param[])
{
  /* Silly but valid. Just changes the local pointer */
  arr_param = NULL;
}
void foo(int *arr_param)
{
  /* ditto */
  arr_param = NULL;
}
Array parameters treated as pointers because of efficiency. 
It is inefficient to copy the array data in terms of both memory 
and time; and most of the times, when we pass an array our 
intention is to just tell the array we interested in, 
not to create a copy of the array.
Two dimensional Arrays:
#include <stdio.h>
#define R 4
#define C 4
void modifyMatrix(int mat[][C])
{
   mat++;
   mat[1][1] = 100;
   mat++;
   mat[1][1] = 200;
}
void printMatrix(int mat[][C])
{
    int i, j;
    for (i = 0; i < R; i++)
    {
        for (j = 0; j < C; j++)
            printf("%3d ", mat[i][j]);
        printf("\n");
    }
}
int main()
{
    int mat[R][C] = { {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12},
        {13, 14, 15, 16}
    };
    printf("Original Matrix \n");
    printMatrix(mat);
    modifyMatrix(mat);
    printf("Matrix after modification \n");
    printMatrix(mat);
    return 0;
}
Output: The program compiles fine and produces following output:
Original Matrix
  1   2   3   4
  5   6   7   8
  9  10  11  12
 13  14  15  16
Matrix after modification
  1   2   3   4
  5   6   7   8
  9 100  11  12
 13 200  15  16
At first look, the line “mat++;” in modifyMatrix() seems invalid. But this is a valid C line as array parameters are always pointers In modifyMatrix()mat is just a pointer that points to block of size C*sizeof(int). So following function prototype is same as “void modifyMatrix(int mat[][C])”
void modifyMatrix(int (*mat)[][c]);
When we do mat++, mat starts pointing to next row, and mat[1][1] starts referring to value 10. mat[1][1] (value 10) is changed to 100 by the statement “mat[1][1] = 100;”mat is again incremented and mat[1][1] (now value 14) is changed to 200 by next couple of statements in modifyMatrix().
The line “mat[1][1] = 100;” is valid as pointer arithmetic and array indexing are equivalent in C.

NOTE:We can’t do mat++ in main() as mat is 2 D array in main(), not a pointer.


WHY DO WE PASS ARRAY LENGTH AS A PARAMETER TO FUNCTION

#include<stdio.h>
void fun(int arr[])
{
  int i;  
  /* sizeof should not be used here to get number
    of elements in array*/
  int arr_size = sizeof(arr)/sizeof(arr[0]); /* incorrect use of siseof*/
  for (i = 0; i < arr_size; i++)
  {
    arr[i] = i;  /*executed only once */
  }
}
int main()
{
  int i;
  int arr[4] = {0, 0 ,0, 0};
  fun(arr);
  /* use of sizeof is fine here*/
  for(i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
    printf(" %d " ,arr[i]);
  getchar();
  return 0;
}
Output: 0 0 0 0 on a IA-32 machine.
The function fun() receives an array parameter arr[] and tries to find out number of elements in arr[] using sizeof operator.
In C, array parameters are treated as pointers So the expression sizeof(arr)/sizeof(arr[0]) becomes sizeof(int *)/sizeof(int) which results in 1 for IA 32 bit machine (size of int and int * is 4) and the for loop inside fun() is executed only once irrespective of the size of the array.
Therefore, sizeof should not be used to get number of elements in such cases. A separate parameter for array size (or length) should be passed to fun(). So the corrected program is:
#include<stdio.h>
void fun(int arr[], size_t arr_size)
{
  int i;
  for (i = 0; i < arr_size; i++)
  {
    arr[i] = i;
  }
}
int main()
{
  int i;
  int arr[4] = {0, 0 ,0, 0};
  fun(arr, 4);
  for(i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
    printf(" %d ", arr[i]);
  getchar();
  return 0;
}

No comments:

Post a Comment