Pointers
Pointers are just variables like any other variables we declare, the only difference is that, the so called normal variables store some sort of data like an integer,a character,a floating point number, on the other hand a pointer stores a logical address belonging to the data or stack segment (at which some data is stored or is to be stored).
A pointer provides us the ability to access and modify data from anywhere. Pointers allow faster access to memory.
Pointer declaration:
The ‘*’ operator is used to declare a pointer for e.g. int *ptr or char *ptr
In the former case ptr is a pointer which would hold the memory location of an integer similarly in the latter ptr is a pointer which would store the memory location of a character. Its important to note that the datatype preceding the identifier is not the datatype of the identifier its the datatype of the value that would be stored or is already present at the location ptr is pointing to.
Pointer Initialization:
Its important to remember that a pointer when declared does not store a valid logical address, rather it holds a garbage value and such pointers are called wild pointers and are very dangerous as they may be pointing to a location where some data is already stored and you might end up overwriting it. So its essential to give a valid address to the pointer (You shouldn’t worry too much about this as the compiler would give you a segmentation fault at run time if you try to access a wild pointer, but its a good habit to initialize the pointer as soon as you declare it).
There are many ways to initialize a pointer:
int *ptr, now this pointer doesn’t have a valid address. We can use the
address of another variable and assign this address to our pointer like
int variable1;
ptr = &variable1;
‘&’ ampersand is used to get memory location of the integer variable.
-
Another way is dynamic memory allocation. In this technique pointer is
assigned a valid address at run time from the heap segment. This is the best way to assign addresses to pointers as it gives us the flexibility of deciding the amount of memory we want our pointer to access and the type of data we will store in the block of memory. Dynamic allocation of memory is done using malloc(), calloc(),and realloc() system calls.
For e.g. lets assign an address to ptr
ptr = (int*)malloc(sizeof(int) * 10);
Here, we type cast malloc to tell the compiler that we want a memory block
that stores integers and we use the sizeof() function to find the size of ‘int’ in
our system and multiply it by the no. of integers we want to store in this
block.
ptr would store the starting address of this block of memory.
-
This last method is specific to character arrays
for e.g. char *ptr = “Hello world”
‘ptr’ is a pointer which would store the address at which a character is to be stored. In our e.g. ptr would hold the address at which ‘H’ is stored using this
address we access the entire string. Note that the string will be automatically terminated by ‘\0′.
Reading Complicated Pointer Declarations:
We’ll use an e.g. to understand how we should interpret complicated pointer
declarations.
int*(*(*ptr[]) () )[]
We should start from the identifier(and the innermost brace) and move right
then left until we reach
end brace so we start from ptr:
-
ptr is the identifier we can straight away conclude that ptr is an array
(on moving right) of (on moving left)pointers, after square brackets the innermost braces close. So we’re at *ptr[]
-
Next on moving right ptr is an array of pointers to a function (then moving left) that returns pointer. At this point we’re at
(int*(*ptr[])() )
-
Finally the outermost braces ptr is an array of pointers to a function returning pointer to (on moving right) an array of integer pointers(on moving left).