Pointers

What are Pointers?

Pointers are aptly name: they “point” to locations in memory.Different from other normal variables which can store values, pointers are special variables that can hold the address of a variable. Since they store memory address of a variable, the pointers are very commonly said to “point to variables”. Lets try to understand the concept.

pointer 1

  • A normal variable ‘var’ has a memory address of 1001 and holds a value 50.
  • A pointer variable has its own address 2047 but stores 1001, which is the address of the variable ‘var’

A pointer variable (or pointer in short) is basically the same as the other variables, which can store a piece of data. Unlike normal variable which stores a value (such as an int, a double, a char), a pointer stores a memory address.

How to Declare a Pointer?

A pointer is declared as :

<pointer type> *<pointer-name>

In the above declaration :

  1. pointer-type : It specifies the type of pointer. It can be int,char, float etc. This type specifies the type of variable whose address this pointer can store.
  2. pointer-name : It can be any name specified by the user. Professionally, there are some coding styles which every code follows. The pointer names commonly start with ‘p’ or end with ‘ptr’An example of a pointer declaration can be :
    char *chptr;

    In the above declaration, ‘char’ signifies the pointer type, chptr is the name of the pointer while the asterisk ‘*’ signifies that ‘chptr’ is a pointer variable.

 

How to initialize a Pointer?

A pointer is initialized in the following way :

<pointer declaration(except semicolon)> = <address of a variable>

OR 

<pointer declaration> 
<name-of-pointer> = <address of a variable>

Note that the type of variable above should be same as the pointer type.(Though this is not a strict rule but for beginners this should be kept in mind).

For example :

char ch = 'c'; 
char *chptr = &ch; //initialize 

OR 

char ch = 'c'; 
char *chptr; 
chptr = &ch //initialize

In the code above, we declared a character variable ch which stores the value ‘c’. Now, we declared a character pointer ‘chptr’ and initialized it with the address of variable ‘ch’.

Note that the ‘&’ operator is used to access the address of any type of variable.

Pointer Operators

There are two  pointer operators: * and &.

The & is a unary operator that returns the memory address of its operand.
m = &count;
places into m the memory address of the variable count. This address is the computer’s internal location of the variable. It has nothing to do with the value of count. You can think of & as returning “the address of“. Therefore, the preceding assignment statement means “m receives the address of count“.
Let us assume that the variable count uses memory location 2000 to store its value. Also assume that count has a value of 100.Then, after the preceding assignment, m will have the value 2000.
The second pointer operator, *, is the complement of &. It is a unary operator that returns the value located at the address that follows. For example, if m contains the memory address of the variable count,
q = *m;
places the value of count into q. Thus, q will have the value 100 because 100 is store data location 2000, which is the memory address that was stored in m. You can think Pointers 115* as “at address.” In this case, the preceding statement means “q receives the value at address m.”
Both & and * have a higher precedence than all other arithmetic operations except unary minus with which they are equal.

Pointer Assignments

You may use a pointer on the right-hand side of an assignment statement to assign its value to another pointer.

For example,

int x;
int *p1, *p2;
p1 = &x;
p2 = p1;
cout<< p2; /* print the address of x, not x's value! */
cout<<(*p2);

Both p1 and p2 now point to x.

Output:

Address of x
value of x

Pointer Arithmetic

The two arithmetic operations  used on pointers: addition and subtraction.Consider example, let ptr be an integer pointer with a current value of 2000. Also, assume integers are 2 bytes long.
After the expression
ptr++;
ptr contains 2002, not 2001. The reason for this is that each time p1 is incremented, it will point to the next integer. The same is true of decrements. For example, assuming that ptr has the value 2000, the expression
ptr–; causes ptr to have the value 1998.

Key points: Each time a pointer is incremented, it points to the memory location of the next element of its base type. Each time it is decremented, it points to the location of the previous element. When applied to character pointers, this will appear as “normal” arithmetic because characters are always 1 byte long. All other pointers will increase or decrease by the length of the data type they point to. This approach ensures that a pointer is always pointing to an appropriate element of its base type.
The expression
ptr = ptr + 26;
makes ptr point to the 26th element of ptr’s type beyond the one it currently points to. You may subtract one pointer from another in order to find the number of objects of their base type that separate the two. All other arithmetic operations are prohibited.

Operations which cannot be performed on pointers are:

  • multiply or divide pointers two pointers
  • apply the bitwise operators to them
  • add or subtract double and float to or from pointers.

 

Pointers and Arrays

Pointers can point at cells of an array not only single variable. Consider this exam

char arr[80], *p1;
p1 = arr;
Here, p1 has been set to the address of the first array element in arr. To access the fifth element in arr,

arr[4]

or
*(p1+3)
Both statements will return the fifth element. Remember, arrays start at 0. To access the fourth element, you must use 3 to index arr. You also add 3 to the pointer p1 to access the fifth element because p1 currently points to the first element of arr

arry in opointer

Reason:
That an array name without an index returns the starting address of the array, which is the address of the first element.There are two methods of accessing array elements: pointer arithmetic and array indexing.Although the standard array-indexing notation is sometimes easier to understand, pointer arithmetic can be faster.
These two versions of pustr()—one with array indexing and one with pointers—illustrate how you can use pointers in place of array indexing. The putstr() function writes a string to the standard output device one character at a time.

 /* Index s as an array. */
 void putstr(char *s)
 {
 int t;
 for(t=0; s[t]; ++t) putchar(s[t]);
 }
 /* Access s as a pointer. */
 void putstr(char *s)
 {
 while(*s) putchar(*s++);
 }

Most professional C/C++ programmers would find the second version easier to read and understand. In fact, the pointer version is the way routines of this sort are commonly written in C/C++.
Summary

  1. An array’s name is a constant pointer to the first element in the array that is a==&a[0] and *a==a[0].
  2. Array indexing is equivalent to pointer arithmetic – that is a+i=&a[i] and *(a+i)==a[i].

Size of Pointer Variable

#include<stdio.h>

int main()
{
int *iptr = NULL;
float *fptr = NULL;
char *cptr = NULL;

printf("\nSize of Integer Pointer   : %d Bytes",sizeof(iptr));
printf("\nSize of Character Pointer : %d Bytes",sizeof(cptr));
printf("\nSize of Float Pointer     : %d Bytes",sizeof(fptr));

return 0;
}

Output :

Size of Integer Pointer   : 4 Bytes
Size of Character Pointer : 4 Bytes
Size of Float Pointer     : 4 Bytes

Arrays of Pointers

Pointers may be arrayed like any other data type. The declaration for an int pointer array of size 10 is
int *x[10];
To assign the address of an integer variable called var to the third element of the pointer array, write
x[2] = &var;
To find the value of var, write
*x[2]
If you want to pass an array of pointers into a function, you can use the same method that you use to pass other arrays—simply call the function with the array name without any indexes. For example, a function that can receive array x looks
like this:
void display_array(int *q[])
{
int t;
for(t=0; t<10; t++)
printf(“%d “, *q[t]);
}
Remember, q is not a pointer to integers, but rather a pointer to an array of pointers to integers. Therefore you need to declare the parameter q as an array of integer pointers,as just shown. You cannot declare q simply as an integer pointer because that is not
what it is. Pointer arrays are often used to hold pointers to strings. You can create a function that outputs an error message given its code number, as shown here:
void syntax_error(int num)
{
static char *err[] = {
“Cannot Open File\n”,
“Read Error\n”,
122 C + + : T h e C o m p l e t e R e f e r e n c e
“Write Error\n”,
“Media Failure\n”
};
printf(“%s”, err[num]);
}
The array err holds pointers to each string. As you can see, printf() inside syntax_error() is called with a character pointer that points to one of the various error messages indexed by the error number passed to the function.For example, if num is passed a 2, the message Write Error is displayed.As a point of interest, note that the command line argument argv is an array of character pointers.

Pointer to a Pointer

You can have a pointer point to another pointer that points to the target value. This situation is called multiple indirection, or pointers to pointers. Pointers to pointers can be confusing.  As you can see, the value of a normal pointer is the address of the object that contains the value desired. In the case of a pointer to a pointer, the first pointer contains the address of the second pointer, which points to the object that contains the value desired

int  **ptr2ptr;

Consider the Following Example :

int num = 45 , *ptr , **ptr2ptr ;
ptr = &num;
ptr2ptr = &ptr;

What is Pointer to Pointer ?

  1. Double (**)  is used to denote the double Pointer
  2. Pointer Stores the address of the Variable
  3. Double Pointer Stores the address of the Pointer Variable

Statement What will be the Output ?
*ptr 45
**ptr2ptr 45
ptr &n
ptr2ptr &ptr

Notes :

  1. Conceptually we can have Triple ….. n pointers
  2. Example : *****n,****b can be another example

Live Example :

#include<stdio.h>

int main()
{
int num = 45 , *ptr , **ptr2ptr ;
ptr     = &num;
ptr2ptr = &ptr;

printf("%d",**ptr2ptr);

return(0);
}

Output :

45

Example 2: 

#include<stdio.h>
#include<conio.h>
void main() 
{
  int i =50;
  int **ptr1;
  int *ptr2;
  clrscr();
  ptr2 = &i;
  ptr1 = &ptr2;
  printf("\nThe value of **ptr1 : %d",**ptr1);
  printf("\nThe value of *ptr2  : %d",*ptr2);
  getch();
}

Output :

The value of **ptr1 : 50
The value of *ptr2  : 50

Explanation :

  1. Variable ‘i’ is initialized to 50.
  2. i is stored at Memory Location 2000.
  3. Pointer Variable ‘ptr2′ stores address of variable ‘i’.
*ptr2 will print [Value Stored at Address 2000 ] i.e 50
  1. Similarly ‘ptr1′ is also a pointer variable which stores the address of Pointer variable [i.e ptr2 stores address of integer variable while ptr1 stores address of another pointer variable].
  2. So

**ptr1 is used to access actual value.

Even though a function is not a variable, it still has a physical location in memory that can be assigned to a pointer. This address is the entry point of the function and it is the address used when the function is called. Once a pointer points to a function, the function can be called through that pointer. Function pointers also allow functions to be passed as arguments to other functions. You obtain the address of a function by using the function’s name without any parentheses or arguments. (This is similar to the way an array’s address is obtained when only the array name, without indexes, is used.)

#include<stdio.h>

void display();

int main()
  {
  void *(*ptr)();
  ptr = &display;
  (*ptr)();

  return(0);
  }

void display()
{
printf("Hello World");
}

Output :

Hello World

Explanation of C Snippet :

Consider normal program –

Now in the above program we have just called function display(), and we get output as “Hello World”.


Consider Scenario using pointer , We should follow following 3 steps to use pointer to call function –

  1. Declare Pointer which is capable of storing address of function.
  2. Initialize Pointer Variable
  3. Call function using Pointer Variable.

Step 1 : Declaring Pointer

void *(*ptr)();
  • We are simply declaring a double pointer.
  • Write () symbol after “Double Pointer“.
  • void represents that , function is not returning any value.
  • () represents that , function is not taking any parameter.

Above declaration tells us ….

Declare Pointer variable that can store address of function which does not return anything and doesn’t take any parameter

Step 2 : Initializing Pointer

ptr = &display;

This statement will store address of function in pointer variable.

Step 3 : Calling a function

(*ptr)();

using (*ptr)() we can call function display();

(*ptr)() = (*ptr)();
         = (*&display)();
         = (display)();
         = display();

thus (*ptr)() is as good as calling function.

Requirement Declaration of Function Pointer Initialization of Function Pointer Calling Function using Pointer
Return Type : None
Parameter   : None
void *(*ptr)();
ptr = &display;
(*ptr)();
Return Type : Integer
Parameter   : None
int *(*ptr)();
ptr = &display;
int result;
result = (*ptr)();
Return Type : Float
Parameter   : None
float *(*ptr)();
ptr = &display;
float result;
result = (*ptr)();
Return Type : Char
Parameter   : None
char *(*ptr)();
ptr = &display;
char result;
result = (*ptr)();

Example 1 : Function having two Pointer Parameters and return type as Pointer

#include<stdio.h>

char * getName(int *,float *);

int main()
{
char *name;
int  num = 100;
float marks = 99.12;

char *(*ptr)(int*,float *);
ptr=&getName;
name = (*ptr)(&num,&marks);

printf("Name : %s",name);

return 0;
}
//-------------------------------------
char *getName(int *ivar,float *fvar)
{
char *str="www.codrsmaze.com";
str = str + (*ivar) + (int)(*fvar);
return(str);
}

Output :

.codersmaze.com

Example 3:

#include <stdio.h>
#include <string.h>
void check(char *a, char *b, int (*cmp)(const char *, const char *));
int main(void)
{
char s1[80], s2[80];
int (*p)(const char *, const char *);
p = strcmp;
gets(s1);
gets(s2);
check(s1, s2, p);
return 0;
}
void check(char *a, char *b, int (*cmp)(const char *, const char *))
{
printf("Testing for equality.\n");
if(!(*cmp)(a, b)) printf("Equal");
else printf("Not Equal");
}

When the check() function is called, two character pointers and one function pointer are passed as parameters. Inside the function check() , the arguments are declared as character pointers and a function pointer. Notice how the function pointer is declared. You must use a similar form when declaring other function pointers, although the return type and parameters of the function may differ. The parentheses around the *cmp are necessary for the compiler to interpret this statement correctly.
Inside check() , the expression

(*cmp)(a, b)

calls strcmp() , which is pointed to by cmp, with the arguments a and b. The parentheses around *cmp are necessary. This is one way to call a function through a pointer. A second, simpler syntax, as shown here, may also be used.

cmp(a, b);

The reason that you will frequently see the first style is that it tips off anyone reading your code that a function is being called through a pointer. (That is, that cmp is a function pointer, not the name of a function.) Other than that, the two
expressions are equivalent.Note that you can call check() by using strcmp() directly, as shown here:

check(s1, s2, strcmp);

This eliminates the need for an additional pointer variable.