C Programming: Pointers
Pointers are one of the most powerful concepts of C programming and it is somewhat difficult for newbies. In this post, I will try to give brief information on pointer declaration and usage, memory access and management and pointers as function parameters.
Variables and Memory Organization of Pointers
Lets have a look at how variables are defined and organized in the memory (RAM) before starting. I am defining an integer named x with the value of 7 by using such a command like int x=7;. There is one more hidden property related with this piece of code: the address of this variable. You may remember from Computer Architecture or Digital Design classes, we need address of the memory cells in order to use (load/store) the data of memory contents. The operations are realized on the addresses of the variables in background.
Pointers are actually a kind of variables however they only store the address of other variables. We can assign numerical values to an integer variable. Like this, we can assign the address of an other variable to the same kind of pointer variable. Lets give a simple example:
1: int x=7; 2: int *y; 3: y=&x; 4: printf("%d\n",*y); //7
In this piece of code, first, an integer named x is defined and value of 7 is assigned. An integer pointer named y is defined in the 2nd line. The address of x is obtained and assigned to y in the 3rd line. 4th line prints the content of pointed value of y (which is 7 in this example). The visual representation of the memory is like somehow below:
Indeed, the address values are imaginary in this example. However, the variable x containing the value 7 is located in the 1000th address of memory. The pointer y which is located at the address 1002 contains the address of x (1000). There are two new operators in the code: * (indirection) and & (address). But, do not confuse the * character in the 2nd line with the indirection operator *. The * in the 2nd line is used just for defining/declaring a pointer. I will give information about the * indirection operator soon.
Pointer Operators
& (address) operator provides the memory address of any variable. We obtained the memory address of x (1000) and assigned this value to y in 3rd line of the code given above (y=1000).
* (indirection) operator provides the value which a pointer points at that moment. *y equals the value of 1000th memory cell (which is 7 in the example). A small question for you. Can you explain the output of the piece of code given below?
5: printf("%d\n",y); 6: printf("%d\n",&y);
5th line prints the value of y which is 1000. 6th line prints the address of y which is 1002.
How can we use pointer variables with scanf?
7: scanf("%d",&x); 8: scanf("%d",y);
If you remember the very first days of learning C programing, you have used & operator for assigning values to variables from keyboard. If you asked a question like “why we are using & with scanf?” to your instructor, probably you received an answer like “we will talk about soon…” Here we are, that “soon” is now!
scanf intentionally needs to know the address of a variable to assign a value from a keyboard input. Thus, we are sending the address of a variable to scanf function in the 7th line (the mystery unveiled). Lets have a look at the 8th line, we do not use & operator when to assign a value to a pointer variables pointing address. Therefore, 8th line assigns a value to x (not y). In other words, 7th line equals 8th line.
Using Pointers as Function Parameters
There are two ways of passing variables to functions in C programming: call by value and call by reference. Please have look at the code given below:
#include <stdio.h> //A program to swap contents of two variables (call by value) void swap(int a, int b){ int temp; temp=a; a=b; b=temp; } void main(){ int x,y; x=3; y=5; printf("x:%d y:%d\n"); swap(x,y); printf("x:%d y:%d\n"); }
The code given above tries to exchange the contents of two integers. However, the output of this code is like this:
x:3 y:5 x:3 y:5
As you can see, the values of x and y remained same before or after calling swap function. Because, x and y defined in the the scope of main function are passed to the swap function and the values of these variables are assigned to a and b variables which are defined in the scope of swap function. The values of a and b are changed in the swap function however, when the cursor exited from swap and returned to main, a and b are inaccessible and the values of x and y of main was keeping their original values. This primary usage of passing variables to functions is named as calling by value. Lets change the code slightly:
#include <stdio.h> //A program to swap the contents of two variables (call by reference) void swap(int *a, int *b){ int temp; temp=*a; *a=*b; *b=temp; } void main(){ int x,y; x=3; y=5; printf("x:%d y:%d\n"); swap(&x,&y); printf("x:%d y:%d\n"); }
In this example, the changes are emphasized in red color, swap function is modified to receive int pointer variables. Therefore, we call the swap function with the address of x and y in main function. So, a and b are storing the address of x and y not 3 and 5. swap function uses indirection operators to access the contents of x and b and exchanges them. When the cursor returns to main, a and b becomes inaccessible besides we do not need them anymore. There is a big difference this time, the output of the modified code will be like this:
x:3 y:5 x:5 y:3
Passing pointer variables to functions is named as calling by reference.
That’s all for now. I will write about the relation between arrays and pointers, dynamic and multi-dimensional pointer arrays soon. See you again!
Rifat Kurban
References
N.E. Çağıltay, C.F. Selbes, G. Tokdemir, Ç. Turhan, C Dersi: Programlamaya Giriş (In Turkish)
P. Deitel, H. Deitel, C: How to Program, 7th Edition