Author : Deepak
Page : 1 Next >>
All of us might have had introductory courses in programming using one of the languages such as C, C++ or Pascal all of which have full support for pointers. There has been a huge division in academic circles regarding the use of pointers. Some say they are good and some say they are the worst things in programming. Anybody who is well versed with pointers would definitely be part of the former school of thought. Then who constitute the latter school of thought? Anybody who has done serious programming would have come across bugs. And anybody who has done good projects using pointers would have come across bugs which he/she would have tried to find out wasting a couple of days possibly and finally discovered the fact that the error was due to a dangling reference or something akin to that. Here we shall demonstrate the use and abuse of pointers using the most popular programming language of modern times, C.
C supports pointers and almost relies on pointers for every non-scalar type. An array is actually a pointer and so is the matrix ( although some prefer to include matrices also under array whereas I prefer to use array for a 1-d array and matrix for 2-d array). You can declare a pointer by the following syntax:
A *a;
where A is a primitive type like int, char etc and a is the instance of a pointer to it. You can set it to point to a location by
a= &b;
where b is to type A. After this operation *a is actually the r-value of b and a is the l-value of b. Hey, i am going too far explaining C. I think that this would be enough about C. To know more refer, The C Programming Language by Kernighan and Ritchie, Prentice Hall Publications.
Pointers can prove to be very handy at times. Can you just imagine what the following code does in an MS-DOS mode:
int main()
{
void interrupt(*old)();
old=0XFFFF0000;
(*old)();
return 0;
}
It just reboots the machine and MS-DOS does allow it to work as it does not have those sophisticated protection features as Windows etc. You can just access any region of memory. But obviously that would not help security and the job of the operating system to ensure security in multiprogramming systems any easier. In DOS the features such as lack of good protection functionalities have been abused in the creation of viruses of the older days and the TSRs (Terminate and stay resident programs).
Pointers are often an efficient tool for resizing data structures and for explicit heap allocation of memory in runtime. We often declare a pointer and issue a system call such as malloc() or calloc() (in C) to gain some heap memory. But often programmers are not careful enough to deallocate then using the free(). What happens? In small programs this does not cause a huge problem. But in certain large programs, we might find ourselves short of memory. Where did the memory go? It is still held in some location that is now not accessible by the program. For example,
void function()
{
int *a=(int *)malloc(1000*sizeof(int));
......
......
return;
}
In such codes where we lose control of memory we allocated there can be abnormal program crashes due to memory deallocation failures that appear almost always transparent to the programmer during his exhaustive debugging session.
There is another problem that of dangling pointers ( or dangling references). What are they? They are pointers to locations that are not meaningful now.
void function(int *b)
{
int a=10;
b=&a;
return;
}
This might appear to be very much correct for the beginner. But a is a dynamic stack variable that is deallocated automatically on return from the function. So when the control returns to the caller of this function the pointer b always points to garbage. Such problems are not obvious to the beginners.
Strings in C (are they strings at all!!) are also basically pointers. Hence there might be problems there also. You cannot directly initialize one string to another but you have to make use of the library function defined in string.h called the strcpy() which duplicates the content in the destination string. e.g.,
char a[]="deepak";
char b[]="india";
a=b;
On the above operations, we lose the area of memory where we stored the string, "deepak" and it cannot be used for any other purpose as it is still under control of the programmer from the system point of view (or rather, it has not been deallocated). This is a very common problem that causes a loss of huge amounts of time in the debugging session.
Due to the need for explicit deallocation for every byte of heap memory allocated, we actually are compelled to do the memory management ourselves. This is the case with C++ and Pascal also. In this era when nobody wants to spend an extra second of time than what is needed, the school of thought that the programmer has to work at a higher level gained upper hand and many technologies were proposed to do these low level works automatically by the system. One of such techniques called garbage collection has gained widespread acceptance. It is being used in JAVA. Here we allocate any amount of memory and do not deallocate it. The system does it for you. This was carried on to C# but the the C# gurus perhaps were very much fond of pointers that they included a wonderful provision. Label a part of code as unsafe and the system will not do any automatic memory management there. You can label such small parts of code as functions even, as unsafe. So pointers may be used safely within 'unsafe' code. But then how can JAVA manage these things without pointers. It has something like a clone of pointers called references. It does not hold any meaningful value until it is allocated memory. And there should be other consequences of pointerlessness. Indeed there are: You cannot pass a scalar by reference (to a function). All objects are allocated from the heap and not from the stack. And worst of them all, the garbage collector comes into play only when the program is short of memory. And what does that mean? The garbage collector works in a small amount of memory and hence works the slowest when it is called. "When you need it the most, it works the worst" says R.W Sebesta in his book the "Concepts of Programming languages".
Seems as if we are moving away from the topic of pointers.
int * function()
{
int a[10];
/* Values filled in a */
return a;
}
Does the above code seem okay to you. Think twice ! The value returned from the function is garbage. What exactly does it convey?. You can return a vector only when it is non-local from a function !But then, a little common sense is enough to understand that then non-local returns are not necessary at all when storing info in the non-local does the job. Is that a limitation. It surely is when you consider that the only way of conveying a string to the caller is to store it in a non-local accessible also to the caller. Many of us would not like it would we?
Another problem arises from the fact that as matrices are pointers to pointers, we do not get enough information on getting a variable and knowing that it points to a matrix. i.e., on getting a variable of type int [][] does not enable us to get any useful information. If we have to access the individual members we have to have two more parameters, the number of rows and number of columns. This is true in the case of 1d arrays also but on getting a 1-d array a, we are not prohibited from accessing a[0], a[1] etc. But on getting a of type int[][], an access to a[1][1] is an error. But whereas if a is of type, int[][10] we can access a[1][1]. This is because C stores the arrays in row major format.
In C there are no bounds for arrays. So even if we allocate only 10 integer space to int * a and call a[100] there is no error but that location might be garbage. We can call a[-10] also without the compiler showing any error. a[b] is actually translated to *(a+b). Then will a[b] and b[a] be the same. It should be even though b is not an array. Try it out. The lack of bound leads us to an advantage as well as a problem. The dynamic resizing of an array is very easy. Just go to the last allocated location and allocate further. But then we are not warned when we access memory beyond our control which might lead
Page : 1 Next >>