DECLARATION AND INITIALIZATION OF POINTERS
In this article we will
look in details of declaration and initialization of a pointer variable. As we know,
pointers are one of the most important and strongest features of C++, it
becomes necessary to know about them in details.
DECLARATION AND INITIALIZATION OF POINTERS
Pointer variables are declared like normal variables except
for the addition of the unary * character. The general form of a pointer
declaration is as follows :
data_type *var_name;
Here data_type is any valid C++ data type and var_name
is the name of the pointer variable.
See some examples of declarations :
When we say that iptr is an integer pointer, it means that the memory location being pointed to by the pointer can hold only integers values. In other words, it can be stated that iptr is a pointer to integer. Similarly, in the above given declarations, cptr is a pointer to a character and fptr is a pointer to floating point value.
Thus, the base type of the pointer defines what type of
variables the pointer can point to.
Note: Technically, any kind of pointer
can point anywhere in the memory. However, all pointer arithmetic is done
relative to its base type, so it is important to declare the pointers
correctly. This is the reason why compiler shows error when we try to assign
variable of a different data type to a pointer of different base type.
How much space does a pointer take?
As a pointer is also a proper data type (derived), it takes space in the memory just like any primitive data type. But the size of a pointer variable is not dependent on its base type. Every pointer, irrespective of its base type, takes 8 bytes of space in memory(64 bit system).
Does an empty pointer take space?
Well, yes. As soon as a pointer is created, it is given an 8 bytes space in the memory. When we assign the address of another variable to it, it simply stores the address value. It is similar to creating, say an int variable and then storing a value to it. Even if no value was assigned to that int variable, it would still take up the space. The memory allocating statement is the declaration and not initialization.
Special Operators for Pointer handling
Two special operators * and & are used with pointers.
The & is a unary operator that returns the memory
address of its operand.
For example,
The above given assignment statement stores the memory address
if i (& returns address of its operand) into iptr so
that iptr is now pointing to the memory location of i. The
expression &i will return an int pointer value because i is
integer type. Similarly, if ch is a character type variable, &ch
will return a character pointer.
To understand the above assignment better, assume that
variable i uses memory location 1000 to store its value. And the value
stored in i is 25, then after the statement iptr = &i, iptr
will have the value 1000.
Following figure illustrates this concept.
The second
pointer operator, *, does the reverse of &. The
unary operator * returns the value of the variable located at
the address following it.
For example,
if iptr contains the memory address 1000, then * iptr will
return the value stored at location 1000.
Following
figure illustrates this concept.
Using ‘*’
operator to change or access the value being pointed to by pointer is
called Dereferencing.
Notes:
The pointer operator * (called “value
at” sign) is the same symbol as multiply operator * and the pointer
operator & (called “address of” sign) is same as bitwise AND
operator &. But these operators have no relationship to each other.
Both pointer operators * and & have a higher precedence than all
other arithmetic operators except unary minus, with which they have
equal precedence.
The operand of & operator can
be any variable or object whose address we need, but the operand of *
operator can only be a pointer variable.
Pointers pointing to incorrect data types
The pointer variables must always point to the correct type of data. For instance, when a pointer is declared to be of type int, the compiler assumes that the address being pointed to by this pointer, will hold integer values.
Consider the following code fragment :
The above code is intended to assign the value of a to b
through the use of pointers, but it will not produce the desired result.
Because iptr is an integer pointer, only 4 bytes (int size is generally
4 bytes) of information will be transferred to b, not the 8 bytes that
normally make up a double type value. Thus, making a pointer point to
incorrect type of data may lead to loss of information.
The “NULL” Pointer Value
A pointer variable must not remain uninitialized since dereferencing uninitialized pointers cause the system crashing. Even if you do not have any legal pointer value to initialize a pointer, you can initialize it with NULL pointer value. Assigning NULL to a pointer initializes it to a value which is not a legal pointer but it saves you from the ‘Big’ problem of uninitialized pointers. A program can later test a pointer against NULL (the zero pointer) to see whether it contains a legal pointer or not.
For example, consider the following code snippet :
Important :
The expression (iptr != NULL) is equivalent to expression (iptr). The zero pointer NULL is
defined in the standard header file stddef.h. NULL is internally mapped
as int 0 (zero).
nullptr – New addition in C++11 standard
Before the release of C++11 standard, defined as NULL filled the role of null pointer. But in C++11, a new keyword namely nullptr has been introduced, which is a distinguished null-point constant. So, now on (provided you are using C++11 standard compilers), you can initialize your pointers with nullptr.
For example,
char * cptr = nullptr;
int * iptr = nullptr;
Difference between NULL and nullptr is that –
NULL is not defined by C++, it is programmer
or compiler defined whereas nullptr has been defined by C++ as a legal
null pointer.
NULL is internally mapped as int 0 (zero)
whereas nullptr is a legal empty pointer which is implicitly convertible
and comparable to any pointer-type.
The inclusion of nullptr also removes a major problem.
Suppose you have two overloaded functions
int f1 (char *) ;
int f1 (int) ;
And we have two pointers as
char * cptr1 = NULL ;
char * cptr2 = nullptr ;
Now the function call f1(cptr1) would
always map to f1(int) and not f1(char *) as NULL is internally mapped as an int.
But f1(cptr2) will always map to the function f1(char *).
Do not stop here. Read all articles related to C++ here.
If you have any doubts, queries or suggestions for the
website, please comment on this post.
If you want to contribute any article for the website, feel
free to share it on coding.nkcoder@gmail.com. We will
publish it on the website with your name.
Download the pdf form of this article here.
Related Topics :
Static and Dynamic Allocation of Memory
Post a Comment