ASIC Verification: C Pointers and Arrays

Sunday, February 24, 2008

C Pointers and Arrays

POINTERS

Pointers are core to the C programming language. They allow us to access memory directly, which lets us write very efficient and thus very fast programs. Most modern programming languages have some form of pointers, and pointers are probably one of the most difficult concepts to master in C.

So, what is a pointer? Basically, it's an address in memory somewhere. We don't know where, and we don't need to know where. That's why we have the pointer. What do we use pointers for? Pointers are one of the most useful concepts in C. The reason is that pointers allow us to keep a single copy of a variable (i.e. the memory we are using) and change that memory from anywhere in the program. This may sound like a bad idea, and in practice, it's a difficult thing to control, but once mastered, you will realize why C is the default standard language for building most any real program today.

ARRAYS

The C language provides a capability that enables the user to design a set of similar data types called "Array". Ordinary variables are capable of holding one value at a time. However, there are situations in which we would want to store more than one value at a time in a single variable. For example, suppose we wish to arrange the percentage marks obtained by 100 students in a class in ascending order, constructing one variable(array variable) capable of storing all the 100 values. An Array is a collective name given to a group of similar quantities. These similar quantities could be all ints, all floats or all chars etc.

What is the connection b/w pointers and arrays in C?

A pointer is a tool used for keeping track of a certain spot in memory. In C, arrays are simply groups of similar data stored sequentially in memory. Because they are stored sequentially, we can keep track of the first item in an array with a pointer to that item, and use that as an index point for every other item in the array.

Usually, the array of characters is called a "string", whereas, an array of ints or floats is called an array. Remember that all elements of any array must be of a same type. So we can't have an array of 10 numbers in which 5 numbers are int and 5 numbers are float. In C we can define variable called marks, which represents not a single value of mark but a entire set of marks. Each element of the set can then be referenced by means of a number called as index number or subscript.

A simple program using an array:

let us try to write a program to find out the average marks obtained by 30 students.
=============================================================
main()
{
float avg, sum=0;
int i;
int marks[30]; /* array declaration*/
for(i=0; i<=29; i++) {
printf("Enter marks\n");
scanf("%d", &marks[i]); /* store data in array*/
}

for(i=0; i<=29; i++)
sum = sum+marks[i];

avg = sum/30;
printf("Average marks = %f\n", avg);
}
=============================================================
in int maks[30], int specifies the type of variable, marks specifies the name of a variable and the number 30 tells how many elements of the type int will be in our array. The bracket ([]) tells the compiler that we are dealing with an array.

Accessing elements of an array

All the array elements are numbered, starting with 0. Thus, marks[2] is not the second element of the array but the third. In our program we are using the variable i as a subscript to refer various elements of an array.

More on Arrays

The features which makes arrays so convenient to program would be discussed below.

Array initialization

How to initialize an array while declaring it? Following are few examples:

int num[6] = {1, 2, 3, 4, 5, 6};
int n[ ] = {2, 4, 6, 8, 10, 12};

Till the array elements are not given any specific values, they are supposed to contain the garbage values.

Array elements in memory

Consider the following array declaration. int arr[8]; It defines an array "arr" of size 8, that is, a block of 8 consecutive objects named arr[0], arr[1], ...,arr[7]. What happens in memory when we make this declaration? 16 bytes get immediately reserved in memory. As the storage class for this array is auto, the initial values for this array is garbage values. Whatever be the initial values, all the array elements would always be present in contiguous memory locations.

Bounds Checking

In C, there is no check to see if the subscript used for an array exceeds the size of the array. Data entered with a subscript exceeding the array size will simply be placed in memory outside the array. This will lead to unpredictable results.

Passing Array elements to a Function

Array elements can be passed to a function by calling the function by value or by reference. Consider the following program.
=============================================================
main()
{
int i;
int marks[ ] = {10, 20, 30, 40,50};

for (i=0; i<=4;i++)
display(marks[i]);
}

display(int m)
{
printf("%d\n", m);
}
=============================================================
Here we are passing an individual array element at a time to a function display() and getting it printed in the function display(). In call by reference, we are passing addressed of individual array elements to function display(). Hence the variable in which this address is collected is declared as a pointer variable.

Pointers and Arrays

Let's talk about pointers in general. A pointer is a number representing a memory address. We call it a pointer because it is pointing to a place in memory. Let's start by how to declare them.

int *ptr; // declares an integer pointer

basically a pointer is declared by putting * in front of a regular variable. Now let us see a simple program that explains the pointer.
=============================================================
main()
{
int i=3, *x;
float j=1.5, *y;
char k='c', *z;

printf("Value of i=%d\n", i);
printf("Value of j=%d\n", j);
printf("Value of k=%d\n", k);

x= &i; y=&j; z=&k;

printf("Original address in x=%u\n", x);
printf("Original address in y=%u\n", y);
printf("Original address in z=%u\n", z);

x++; y++; z++;

printf("New address in x=%u\n", x);
printf("New address in y=%u\n", y);
printf("New address in z=%u\n", z);
}
=============================================================

Suppose i,j and k are stored in memory at addresses 1002, 2004 and 5006, then the output would be;

Value of i=3
Value of j=1.5
Value of k=c
Original address in x = 1002
Original address in x = 2004
Original address in x = 5006
New address in x = 1004 // integer occupies 2 bytes
New address in y = 2008 // float occupies 4 bytes
New address in z = 5007 // character occupies 1 byte

The method of accessing array elements by using subscripted variables is already known to us. Next we will see accessing array elements by using pointers.
=============================================================
main()
{
int num[ ] = {1, 2, 3};
int i, *j;

j=&num[0];

for(i=0;i<=2;i++);
{
printf("Address = %u\n", j);
printf("Element = %d\n", *j);
j++;
}
}
=============================================================
Accessing array elements by pointers is always faster than accessing them by subscripts. However, array elements should be accessed using pointers if the elements are to be accessed in a fixed order. Instead, it would be easier to access the elements using a subscript if there is no fixed logic in accessing the elements.

Passing an entire array to a function

How to pass an entire array to a function rather than its individual elements. Consider the following example.
=============================================================
main()
{
int num[ ]={1, 2, 3};
display(&num[0], 3);
}
display(int *j, int n)
{
int i;
for(i=0; i<= n-1; i++)
{
printf("Element = %d\n", *j);
j++;
}
}
=============================================================
The Real Thing

int num[ ] = {1, 2, 3};
We know that on mentioning the name of the array, we get the base addresses. Thus, by saying *num we would be able to refer to the zeroth element of the array, that is, 1. One can easily say that *num and *(num+0) both refers the 0th element.
Similarly by saying *(num+1) we can refer the first element of the array, that is, 2. In fact, this is what the C compiler does internally. When we say, num[i], the C compiler internally converts it into *(num+i). This means that all the following notations are same.

num[i] == *(num+i) == *(i+num) == i[num]

More than One Dimension

It is also possible for arrays to have two or more dimensions. Consider the following program that stores roll numbers and marks obtained by a student side by side in a Matrix.
=============================================================
main()
{
int stud[4][2];
int i,j;
for (i=0; i<=3; i++)
{
printf("Enter the roll number and marks\n");
scanf("%d%d", &stud[i][0], &stud[i][1]);
}
for (i=0; i<=3; i++)
printf("%d %d\n", stud[i][0], stud[i][1]);
}
=============================================================
in stud[i][0] and stud[i][1] the first subscript of the variable stud, is row number which changes for every student. The second subscript tells which of the two columns we are talking about. The zeroth column which contains the roll number or the first column which contains the marks. Remember, the counting of rows and columns begin with zero.

Initializing a 2-D array

How do we initialize a two D arrays?

int stud[4][2] = { {1200, 56}, {1201, 45}, {1202, 87}, {1203, 66}};

While initializing an array it is necessary to mention the second column, whereas the first column is optional. Thus, the following declaration are perfectly acceptable.


int arr[2][3]={12,34,56, 23,54,67}; int arr[][3] ={12,34,56, 23,54,67} whereas

int arr[][]={12,34,56, 23,54,67}; int arr[2][] ={12,34,56, 23,54,67} would never work.

Questions

What are the differences between structures and arrays?
Difference between arrays and linked list?
What is the difference between Strings and Arrays?
Are the expressions arr and *arr same for an array of integers?
How would you dynamically allocate a one-dimensional and two-dimensional array of integers?
How can you increase the size of a dynamically allocated array?
How can you increase the size of a statically allocated array?

Reference

"Let Us C" by Yashavant Kanethar.

No comments: