Pointers
Pointer variables are the variables capable of holding the addresses. Before using a pointer variable we must declare the variable as a pointer variable as we declare any other variable. But we must use an indirection operator while declaring a pointer variable.
In the above program you can get the address of the variable i by displaying the contents of pointer variable j and you can even see the address of the pointer variable j by prefixing the ampersand sign with the pointer variable j as shown in the example.
Consider the following examples:
Now although i occupies 2 bytes in memory, the statement ptr1 = &i; stores only the address of the first byte i.e. 9308 in ptr1.
As we can see from the output memory locations addressed as 9308 and 9309 is allocated to the integer variable i.
Similarly ptr2 = &j; stores only the address of first byte i.e., 9300 out of 4 bytes allocated to j. As we can see from the output, memory locations addressed as 9300, 9301,9302 and 9304 is allocated to the float variable j; similarly the memory location 9295 is allocated to the character variable c.
This address of the first byte is often known as the base address. Although ptr1 and ptr2 are containing only the base address, *ptr1 and *ptr2 will allow the access to all the bytes occupied by the integer variable
i and float variable j respectively. That is why, while defining the pointers, we are defining it by the type of variable’s value it can hold.
Pointer arithmetic is different than the normal arithmetic. This is because in pointer arithmetic when you increment the pointer or decrement the pointer the quantity by which the pointer increments or decrements depends on the type of the pointer on which the operation is performed.
Increment/Decrement operation:
When you increment or decrement an integer pointer it increments or decrements by two because each of the integer variables are assigned with two bytes. Similarly when you increment or decrement a float pointer it increments or decrements by four because each of the float variables are assigned with four bytes and when you increment or decrement an character pointer it increments or decrements by only one because each of the character variables are assigned with one byte.
In the above example address of the variable i is 8728 and when we add 5 to the contents of pointer variable ii it is incremented to 8738 because the integer variable is allocated two bytes. Thus 2 ? 5 = 10.
In the above example address of the variable f is 9280 and when we add 5 to the contents of pointer variable ff it is incremented to 9300 because the float variable is allocated four bytes. Thus 4 ? 5 = 20. Similarly when the pointer is decremented by two it's contents are reduced by 8 numbers which is shown in the above example i.e. 9292.
In the above example the value of the radius is copied on to the variable r in the function area();
In this the value of the actual arguments in the calling function are copied onto the formal arguments of the called function.
This means that even if we make changes to the values of the formal variables in the called function the value of the actual arguments in the calling function will not change.
If suppose the value of the variable radius is 5.0 when it was passed to the function area(), but assume if we change the value of the variable r to 10.0 in the function area(), this change will not reflect in the value of the variable radius in the function main() and it is 5.0 only.
In the above example the address of the radius ( &radius- This ampersand sign(&) prefixing the variable radius means that the address of the variable radius) is copied on to the variable r in the function area(); In the function area(), to catch this address the variable r should be a pointer variable so it is depicted with float *r; to mean that r is the pointer variable.
In this the address of the actual arguments in the calling function are copied onto the formal arguments of the called function. This means that if we make changes to the values of the formal variables in the called function the value of the actual arguments in the calling function will change.
If suppose the value of the variable radius is 5.0 when it was passed to the function area() but assume if we change the value of the variable pointed by r to 10.0 in the function area(), this change will reflect in the value of the variable radius in the function main() because the pointer variable r is pointing to the variable radius. Following example shows this.
In the above example value of radius when it was passed to the function area() was 5.0. But once the area was calculated with this value the value of the radius was changed with the help of the pointer variable r to 10.0 and again the area was calculated. This new value is reflected in the value of actual argument radius.
In this, the address of a and b are copied on to x and y respectively. So whatever changes are made at the locations pointed by x and y it will affect the values of a and b.
When we define one-dimensional array, it is been allocated the consecutive locations in memory. For example if we have declared an array int ar[5]; then the compiler allocates 10 bytes as each location means two bytes as the data type is integer. Following example explains this concept of contiguous allocation.
As you can observe from the output that starting from memory location 9170 to 9179 ten bytes are allocated for the integer array named as ar with size as five elements. The allocation is continuos memory location.
In the above example, we are assigning the address of 0th element of array ar to pointer variable ptr. Later we are incrementing the pointer variable ptr to point to the next element of array ar. Thus the for loop will continue till the last element of array ar is accessed using pointers. Thus by assigning ptr=&ar[0] we have collected the base address of ar in the pointer variable ptr i.e. in the main() function disp() is called by passing the address of the starting element of array ar[ ] and in the function disp() the address is received by the pointer variable ptr.
Note:
In the above example, during the first iteration of for loop in main() we are passing the address of the 0th element of the array ar[ ] to the function disp() and using the pointer the 0th element of array ar[ ] is displayed. So in the function disp(), ptr is the pointer variable which will have the address of the 0th element of array ar[ ]. During the successive iterations of for loop, addresses of each and every element of array ar[ ] is passed to the function disp() and the element is displayed. Thus, by putting for loop in the main, we are passing the address of 1 element at a time.
In the above example the base address of the array strn[ ] is passed to the function length() using the pointer variable p in the main(). The address is received in the function length() by the pointer variable ptr. Simple while loop is used in the function length() to advance the pointer ptr till the end of the string as we know that the string is terminated by a null (‘\0’) character. The contents of pointer are increased till a null character is encountered. The length of the string is printed in the function length() itself.
Let us consider again the program to find the length of a string using pointers and functions. But in this we are returning back the value of length of the string back to the function main() through a return statement in function length() and the value sent back from the function is received by the variable len and it’s value is printed in the main()
Let us consider again another program to find the length of the string. In this program the length of the string is printed in the main() function itself. Here both the arguments passed to function length() are pointers.
In the above program ptr1 and ptr2 are the pointers in the function length(), ptr1 pointing to the array variable strn[ ] and ptr2 is pointing to the variable len. Here the length is printed in the main() function and value of the variable len is not exclusively returned back to main() but it is available because the value of variable len is changed in the function length() by the statement *ptr2= *ptr2 + 1.
Consider a two dimensional array having five rows and two columns for example int test[5][2]; The elements and the assumed memory locations are given above.
Since the memory is allocated continuously first four memory locations (150, 151, 152, 153 as each element is allocated two bytes because it is an integer array) correspond to first row, next four memory (154,155,156,157) locations correspond to second row and last four memory locations (166,167,168,169) correspond to last row. Thus two elements each are considered as one-dimensional array of two elements each.
When we are talking of pointers with 2 dimensional array, C language has a powerful capability of treating each row of a 2-dimensional array as a one dimensional array. This is a very important fact if we wish to access array elements of a two-dimensional array using pointers. Thus, the declaration int test [5][2] can be considered as setting a five one-dimensional array, each of which is a one-dimensional array of two elements long array. We refer to an element of one-dimensional array using a subscript. Similarly, if we can imagine test to be a one-dimensional array then we can refer to its 0th element as test[0], the next element as test[1] and so on. By writing like this you will get the address of 0th element, 1st element and so on.
Analyzing the output of above program, the compiler knows that test is an integer array. So, each element of this array occupies 2 bytes. There are 2 elements in a row. So, each row takes 4 bytes. Thus each row starts 4 bytes further along from the last one as can be shown in the earlier shown memory map of the array.
The compiler knows how many columns are there in the array since we have specified it in the array declaration. So it interprets test [0] at address 8698 and test [1] at 8702 and so on. So, now we have reached each individual row and we have to refer to the individual elements of this row. Suppose we want to refer to the element test [2][1] using pointer notation then, we know that test [2] will give the address 8706, the address of second one-dimensional array. So by writing 8706+1 we will get the address 8708. (Since it is not an ordinary arithmetic but pointer arithmetic). So it is now test [2]+1 will give us the address 8708 and value at this address can be obtained by * (test [2]+1). The above expression gives us the value 6, which is stored at that array location. This explanation is shown with the program given below.
The address allocated for the array is different in this because each time you execute a program the address allocated may be different. But the concept behind the explanation remains the same.
Files << Previous
Next >> Structures and Unions
Our aim is to provide information to the knowledge seekers.