pointers in c

Pointers in C/C++ programming with examples program

Pointers are a very important feature of the C/C++ programming language. You can not imagine C language without the pointers and you could not be a great C programmer without a good knowledge of the C pointers.

In this blog post, you will learn about the pointers in C/C++; what are pointers, what are types of pointers, how do you use pointers in C/C++ programming,  how to apply a mathematical operation on pointers, and the common mistakes with pointers. I have already cover these topics separately in detail but here I want to give a short description which helps you in revision if you are preparing for the interview. So let see the pointers and their concept in detail.

 

What is a pointer in C?

A pointer is a special variable that stores a memory address. Pointers are used to store the addresses of other variables or memory items. The basic difference between the pointers and the simple variable is that the pointers store the addresses rather than values.

Because the pointer references a location in memory, so we can access the value of the reference memory location using the pointer, the technique to access the value is known as dereferencing the pointer. We will discuss it in the below of article.

 

Short Notes: Pointer stores a memory address.

 

Pointer Syntax (Declaration of pointers in C/C++):

Like the other C/C++ variables, before using a pointer you have to declare it first. The declaration of a pointer is very important because at the time of declaration you define the capability of the pointer. Every pointer has the data types (pre-defined or user-defined) and names followed by an asterisk (*). Asterisk is a unary operator.

Pointer Syntax:

Data_Type * Pointer_Name;

 

Let’s see the below-mentioned example to understand the declaration of a pointer.

char *cPtr // pointer to a character

int *iPtr; // pointer to an integer

float *fPtr; // pointer to float

double *dPtr; // pointer to a double

 

How to use pointers in C/C++ Programming?

I think before understanding how to use the pointers, we should know the two important unary operators. These unary operators are indirection operator ( * ) and address of operator ( &).

 

Indirection operator or Dereference Operator (  * ):

The unary * operator (Asterisk) denotes indirection. With pointers, the indirection operator is used for two things, to declare a pointer variable and to access the value stored in the address (accesses a value indirectly through a pointer).

 Let see an example,

//Use of indirection operator in declaration of pointer
int *iPtr; 

/*Use of indirection operator to read 
the value of the address pointed by the pointer*/
a = *iPtr; 

/*Use of indirection operator to write the 
value to the address pointed by pointer*/
*iPtr = a;

 

The operand of * must be a pointer type and the result of the operation is the value addressed by the operand. If the operand of indirection operator has type ‘‘pointer to type’’, the result of the operation has type ‘‘type’’.

Let’s understand it with an example, suppose ptr is a “pointer to an integer“, so when we will use *(indirection operator) with ptr, it will yield an “integer“.

 

Imp Note: If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.

Some of the most common conditions that invalidate a pointer value:

 

1). Dereferencing a pointer by the indirection operator (*)  that specifies the address of an object after the end of its lifetime (such as an object that’s gone out of scope or that’s been deallocated).

//https://aticleworld.com/dangling-pointer-and-memory-leak/

#include<stdio.h>

int *Fun()
{
    //Local variable
    int Data = 5;
    
    //Address of local variable
    return &Data;
}

int main()
{
    //Returning address of the local variable
    int *piData = Fun();
    
    //Use of indirection operator with pointer
    printf("%d", *piData);
    
    return 0;
}

 

2). Dereferencing a pointer by the indirection operator (*) that are a null pointer.

3). Dereferencing a pointer by the indirection operator (*) that specifies an address not used by the executing program.

4). Dereferencing a pointer by the indirection operator (*) that specifies an address that is inappropriately aligned (Unaligned) for the type of the object pointed to.

Unaligned memory accesses occur when you try to read N bytes of data starting from an address that is not evenly divisible by N (i.e. addr % N != 0).

For example, reading 4 bytes of data from address 0x10008 is fine, but reading 4 bytes of data from address 0x10007 would be unaligned memory access.

See the below code, The line number 8 would give an unaligned memory for a “pointer to the long”. The effects of performing unaligned memory access vary from architecture to architecture.

#include<stdio.h>

int main ()
{

    long ldata = 0x12345678;

    void *vptr = (char *)&ldata + 1;

    //address not aligned with long
    long *lptr = vptr;

    ldata = *lptr;

    printf("%lx\n",ldata);
    
    return 0;
}

 

Address of operator ( & ):

It is also a unary operator and gives the address of the operand. According to the C standard “The operand of the unary & operator shall be either a function designator or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier”.

 Let see an example,

int data = 0; // declaration  of integer variable

&data  => Give the address of the data

int *pData ; // declaration  of pointer

&pData => Give the address of the pointer

 

Now I think you have sufficient required knowledge of & and * unary operators. So need to come on the topic “how to use pointers”.  So we require mainly three steps to use the pointers in the programs these are mentioned below.

1.) Declare a pointer:

// declaration of pointer to int

int  *iPtr = NULL; 

 

2.) Assign an address to the pointer:

Let’s take an example.

int* iPtr, data;

data = 20;

iPtr = &data;

Here, 20 is assigned to the data (integer variable), and the address of data is assigned to the iPtr (integer pointer).

3.) Access the pointers:

To access the value of the address pointed by the pointers, we use the * operator. For example:

int* iPtr, data;

data = 20;

iPtr = &data;

printf("%d", *iPtr);  // Output: 20


*iPtr = 5; //change the value through point

printf("%d", data);  // Output: 5

Here, the address of data is assigned to the iPtr integer pointer. To access the value stored in that address, we used *iPtr.

 

Let see a C program for better understanding. In the below C program, I am creating an integer pointer (iPtr), and using this printer I am accessing an integer variable (data).

#include <stdio.h>

int main (void)
{

    int  data = 20;   // declaration of variable

    int  *iPtr = NULL; // declaration of pointer

    iPtr = &data;  // Assign address of data to the pointer

    printf("Address of data: %p\n\n", &data);

    //Address stored in pointer
    printf("Address stored in iPtr: %p\n\n", iPtr);

    //Read value from the stored address with help of pointer
    printf("value of *iPtr = %d\n\n", *iPtr );

    //Assign value to the stored address with help of pointer
    *iPtr = 5;

    //Again Read value from the stored address with help of pointer
    printf("New value of *iPtr = %d\n\n", *iPtr);

    printf("data = %d\n\n", data);


    return 0;
}

Output:

c pointers

 

 

Watch this video to see how to declare a pointer and how to use the pointer in the program.

 

 

How do a pointer work in C?

We have already seen three important require steps to use the pointers in the programs. Here we will discuss the second (“Assign an address to the pointer“) and the third (“Access the Pointer“) steps in detail.

So let’s assume in the program you have created an integer variable iPtrand assigned the value 10. Let’s suppose the unique address of the variable  iPtr is 0x23567891. See the below image.

pointers in c

 

We already know that using the & unary operator we can get the address of the variable. So here I am going to create a pointer to an integer piData and assigning the variable address to the pointer. See the below image.

Note: In the below image, the variable name is wrong basically it is iPtr.

understanding and using c pointers

 

 

Let’s see the above discussion in the form of the Code.

//Create an integer variable and assign 10
int iPtr = 10;


/*Create an pointer to an integer 
and assign the address of the iPtr*/
int *piData = &iPtr;

 

Note: You must always initialize the pointer. At the time of pointer declaration, if you don’t have a valid address, you can assign the pointer with NULL.

 

 

Now pointer piData is pointing to a variable iPtr address. Let’s see how we can access the variable (iPtr) value using the pointer piData.

Get the value from the address Pointed by Pointer:

We already discuss that using the unary operator * (Asterisk) we can access the value stored in the address. So to get the value of the variable address pointed by the pointers, we use the * operator.

For example,

Here, the address of the iPtr ( integer variable ) is assigned to the piData (integer pointer). To get the value using the pointer stored by the variable iPtr, we used the statement *piData. You can see in the below code, in printf() we have used *piData.

//Create an integer variable and assign 10
int iPtr = 10;


/*Create an pointer to an integer 
and assign the address of the iPtr*/
int *piData = &iPtr;


printf("%d", *piData);   // Output: 10

 

Changing the value of the address Pointed by Pointer:

Let’s consider the above-mentioned example. where the address of the iPtr ( integer variable ) is assigned to the piData (integer pointer).

When we write the statement *piData = 14; The indirection operator (*) is used to store the int value (14) at the address stored in piData  and the value of the iPtr will change since piData and the address of iPtr is the same.  See the pseudo-code.

//Create an integer variable and assign 10
int iPtr = 10;


/*Create an pointer to an integer 
and assign the address of the iPtr*/
int *piData = &iPtr;

printf("%d", *piData);   // Output: 10


//Assign 14 to *piData
*piData  = 14;

//print *piData
printf("%d", *piData);   // Output: 14


//print iPtr
printf("%d", iPtr);   // Output: 14

 

 

Note:  We can not use the indirection operator ( * ) directly on void pointers.

 

Example: Working of Pointers:

Let’s consider the above explanation and create a working example. It will help to visualize the above-mentioned scenarios.

#include <stdio.h>

int main()
{
    //Create an integer variable and assign 10
    int iPtr = 10;
    /*Create an pointer to an integer
    and assign the address of the iPtr*/
    int *piData = &iPtr;

    printf("\n Value of the variable = %d\n\n\n", iPtr);


    // Using *piData indirectly we can get the value of iPtr
    printf(" print the value of variable using the pointer = %d\n\n\n", *piData);


    //Assign indirectly 14 to iPtr
    (*piData) = 14;

    printf(" Value of the variable = %d\n\n\n", iPtr);

    printf(" print the value of variable using the pointer = %d\n\n\n", *piData);

    return 0;
}

Output:

 

 

 

 

Watch this video to see how to pointer works in programming.

 

 

Some Important types of pointers in C:

Here I will give you a short description of on different types of pointers that we used frequently in C programming. I have already covered these topics in separate blog posts. So let’s see some important types of pointers in C.

Null Pointer:

According to the C standard, an integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer.

Example of a null pointer.

int *ptr = NULL; // ptr is a null pointer

 

Void pointer:

A void pointer is a generic pointer, it has no associated data type. It can store the address of any type of object and it can be type-casted to any type. According to the C standard, the pointer to void shall have the same representation and alignment requirements as a pointer to a character type. A void pointer declaration is similar to the normal pointer, but the difference is that instead of data types we use the void keyword.

Example of the void pointer.

void * vptr; //vptr is a void pointer

Wild pointer:

A pointer that is not initialized properly before its first use is known as the wild pointer. Uninitialized pointer’s behavior is undefined because it may point to some arbitrary location that can be the cause of the program crash, that’s is the reason it is called a wild pointer.

Note: Generally, compilers warn about the wild pointer.

 

Dangling pointer:

Generally, daggling pointer arises when the referencing object is deleted or deallocated and your pointer still pointing to a memory location. It creates a problem because the pointer is pointing to the memory that is not available. When the user tries to dereference such type of pointer, it shows the undefined behavior and can cause the segmentation fault.

In simple words, you can say that “a dangling pointer is a pointer that points to invalid memory or to memory that is not valid anymore and can be the cause of the undefined behavior”. Let’s see the below image for a better understanding.

In the image Pointer1, Pointer2 is pointing to a valid memory object but Pointer3 is pointing to a memory object that has been already deallocated. So Pointer3 becomes a dangling pointer when you will try to access the Pointer3 then you will get the undefined result or segmentation fault.

dangling pointer

You can see Articles for more detail,

Note: Near, Far and Huge pointers are some old concepts used in 16-bit intel architectures in the days of MS-DOS, not much use anymore.

Near pointer:

A near pointer is a pointer that is used to bit address of up to 16 bits in a given section of the computer memory that is 16 bit enabled. The limitation is that we can only access 64 kb of data at a time.

Far pointer:

A far pointer is typically 32- bit pointer that can access memory outside the current segment. To use this, the compiler allocates a segment register to store segment address, then another register to store offset within the current segment.

Huge pointer:

Huge pointers are essentially far pointers and the size is the same as far pointer (32 bits). It can also access bits that are located outside the sector. But huge pointers have an explicit selector. When you do pointer arithmetic on them though the selector can change (Not modify in case of far pointer and it is fixed for it).

Complex pointer:

For pointers with multiple levels of indirection, dereferencing operations can be complicated. I will discuss it in a separate blog post.

 

Arithmetic Operation on Pointers in C:

Like other variables, we can also apply some allowed arithmetic operations on pointers. Here I will not go into details but I have already written a blog post that covers almost all things related to the arithmetic operation on pointers. It is my recommendation you should read this post, Arithmetic Operators On Pointers.

Let’s see a table that contains some important arithmetic operators which frequently used with pointers.

Indirection (*) The indirection operator is used for two things, to declare a pointer variable and to access the value stored in the address.
Reference operator (&) This operator is used to get the address of the variable or pointer.
Assignment (=) You can assign the value to the pointer or the value to the address which is pointed by the pointer.
Addition (+) You can add integer values to the pointer to point to the different memory locations.
Subtraction (-) You can subtract the integer value from the pointer to point the different memory locations.
comparison (==, !=, <, >, <=, and >=) This operation is valid only between two pointers that point to the same array.
Incrementing (++) You can use increment operators (pre and post) with the pointer.
Decrementing (--) You can use decrement operators (pre and post) with the pointer.

 

Note: When we increment or decrement the pointer then the pointer increase or decreases a block of memory (block of memory depends on pointer data type).

 

How does pointer arithmetic work

When we increment or decrement the pointer then the pointer points to the next or previous memory location. Generally, people make mistakes, when they calculate the next pointing address of the pointer.

Here is the technique to calculate the next pointing address of a pointer when applying any arithmetic operation on it. To understand this technique let us consider ptr is a pointer that has data type T and i” is the pointer offset.

addr( ptr + i ) = addr( ptr ) + ( sizeof( T ) * i );
addr( ptr - i ) = addr( ptr ) - ( sizeof( T ) * i );

 

Let see an example for better understanding where I am incrementing the pointer to the float. I am “assuming that the size of the float is 4 bytes”.

So first need to create a pointer to the float and initialize it will NULL.

float *pfData = NULL;

When we increment the pfData then it points to the next float location without impacting the stored data. Because here we are assuming float size is 4 bytes. So when we increment the pfData by 1 then it will point to the address which will be just 4 bytes more than the current pointing address.

pfData++;

 

arithmatic operation on float pointer
Let us see how is the above technique work to calculate the next pointing address for the pfData (pointer to float).

addr( pfData + 1 ) = addr( pfData ) + [ sizeof( float) * 1 ];

addr( pfData + 1 ) = addr( pfData ) + [ 4 * 1 ];

addr( pfData + 1 ) = addr( pfData ) + 4;

 

So supposes if pfData initially points to an address “2000”, then after the pfData++ it will point to “2004“.

pfData++; ==> pfData = pfData + 1 => 2000 + 1*4 => 2004

 

Program to increment a pointer in C:

let’s see a program to understand the effect of increment operators on pointers. In the below C program, I am creating a character and float pointer and applying the increment operators. After applying the increment operator on the pointer I am printing the address which is pointing by pointers.

#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{

    char *pcData = NULL; //pointer to character

    float *pfData = NULL; // pointer to float

    printf(" Address of character pointer before incrementation = %d\n\n\n", pcData);

    printf(" Address of float pointer before incrementation = %d\n\n\n", pfData);

    pcData++;  //Increment the character pointer by one

    pfData++; //Increment the float pointer by one


    printf(" Address of character pointer After incrementation = %d\n\n\n", pcData);

    printf(" Address of float pointer After incrementation = %d\n\n\n", pfData);



    return 0;
}

Output:

 

 

 

 

If you love online courses and want to learn C programming, you can check the below courses it will help.

 

Uses of pointers with different identifiers in C/C++:

Identifiers” or “symbols” are the names you supply for variables, types, functions, and labels in your program.  We can use the pointers with variable, pointer, array, structure, union or function ..etc.  We have already seen that how we can use the pointer with variables. here you will see a small discussion that how we can use the pointer with the array, structure, and function. I  have already written a detailed article on it. I will mention the article link with the appropriate identifier.

 

Pointer and Array in C:

First, you need to understand that “pointers and arrays are not the same”. An array is essentially a collection of elements. The data type of all elements must be the same and store at the contiguous memory location.

In C-language pointer and array are very close to each other. Actually, In most contexts, array names decay to the pointers. So if aiData is an array of integers then “aiData” will be the address of its first element. You can also say that “aiData” is similar to &aiData [0].

Let’s see a program example,

#include <stdio.h>


int main(int argc, char *argv[])
{

    int aiData[5] = {10,5,6,7,8}; //integer array

    printf("Address of first element %p\n\n",&aiData[0]);

    printf("Address of first element %p\n\n",aiData);

    return 0;
}

Output:

 

 

 

Relationship between array and pointer in C

Already I have explained that pointer and array are not the same. In most contexts, array names decay to pointers except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literals used to initialize an array.

Array elements stores in a consecutive memory block. We access the array elements using the index. But we can also access the array elements with the help of a pointer. Let’s see an example.

Consider the following example. Let suppose acBuffer is an array of characters.

#include <stdio.h>

int main()
{
    int i = 0;
    char acBuffer [ ] = {'a','t','i','c','l','e'};

    for(i = 0; i < sizeof(acBuffer); ++i)
    {
        printf("&acBuffer[%d] = %p\n", i, &acBuffer[i]);
    }

    printf("\nAddress of array acBuffer: %p\n\n", acBuffer);

    return 0;
}

Output: 

relationship array and pointers in C-min

 

So acBuffer[0] is the 0th element of the array like that acBuffer[i] is the ith element of the array.

Notice that the address of &acBuffer[0] and acBuffer is the same. So from the above example, it is clear that &acBuffer[0] is equivalent to acBuffer . And, acBuffer[0] is equivalent to *acBuffer .

Similarly &acBuffer[1] is equivalent to acBuffer+1 and acBuffer[1] is equivalent to *(acBuffer+1).

So for ith elements, it would be.

*(acBuffer+ i) = acBuffer[i];

(acBuffer+ i) = &acBuffer[i];

 

Let’s see an image for a better understanding,

Note: Because acBuffer is an array of characters then &acBuffer[i] type is the pointer to the character and its value is the address of the ith element of the acBuffer.

 

I believe now you are able to understand the relationship between an array and pointer. Now it’s time to understand that how we can access the array elements using the pointer.

To access the element of the array through the pointer we need to create a pointer type the same as the array first element (here, a pointer to char).

char * pcBuffer = NULL;

pcBuffer = acBuffer; // character pointer point the address of first element

 

Now using the pointer you can access all elements of the array.

#include <stdio.h>

int main(int argc, char *argv[])
{

    char acBuffer [] = {'a','t','i','c','l','e'};   // array of character
    int i = 0;
    char *pcBuffer = NULL; // character pointer

    pcBuffer = acBuffer;

    for(i =0; i <6; i++)  // access the array element using the pointer
    {
        printf("pcBuffer[%d] = %c  or  *(pcBuffer+%d) = %c \n\n",i,pcBuffer[i],i, *(pcBuffer+i));
    }

    return 0;
}

Output:

 

 

 

 

 

 

 

Difference between pointer and array:

From the beginning, I am saying that the pointer and array are not the same. Here we will see the difference between the array and pointers. I have already written a blog post on it if you want you can check it, “Difference between the array and pointers“.

The basic difference between array and pointers is that the array is a sequence of elements of the same type that occupy a contiguous area of memory while the pointer is a special variable that stores a memory address.

The array is a non-modifiable type while we can change the address which pointed by pointers if the pointer is not a constant type. Let’s see an example code where I am trying to modify the array.

Consider the below example,

In the below example when trying to modify the array then we will get the compiler error.

array using pointer

 

 

Pointer and function:

We can use the pointers with functions like other identifiers. A pointer to a function is similar to the other pointers but the only difference is that it points to the address of the executable code of the function. In the other word, we can say, a function pointer is a type of pointer that store the address of a function.

You can use pointers to call functions and to pass functions as arguments to other functions. You cannot perform pointer arithmetic on pointers to functions.

Declaration of function pointers in C:

The declaration of a function pointer is quite simple as you can think. It seems difficult in beginning but once you are familiar with the function pointer it becomes easy. The type of a pointer to a function is based on both the return type and parameter types of the function.

The declaration of a pointer to a function is similar to the declaration of a function that means the function pointer also requires a return type, declaration name, and argument list. One thing that you need to remember here is, whenever you declare the function pointer in the program then the declaration name is preceded by the * (Asterisk) symbol and enclosed in parenthesis.

Let’s take an example to understand the declaration of a function pointer. Suppose you want to declare a pointer to a function that points to a function that takes an int as an argument and returns nothing.

void ( *fpData )( int );

Explanation:

In the above expression, fpData is a pointer to a function that is taking one argument, int, and returning void (means nothing). Braces play important roles when we are declaring a pointer to a function.

If in the above example, I remove the parentheses, then the meaning of the above expression will be changed and it becomes void * fpData (int). It is a declaration of a function that takes the int as arguments and returns a void pointer.

 

Note: A declaration of a pointer to a function must have the pointer name in parentheses.

 

List of some function pointers:

A pointer to a function must have the same signature as the function that it is pointing to. In a simple word, we can say that the function pointer and its pointed function should be the same in the parameter list and return type.

In the below list, I have given some function pointers for your practice and I want you to write about the listed function pointer in the comment box.

void (*fpData)(void);

int  (*fpData)(int);

int  (*fpData)(char *);

int* (*fpData)(char *);

int  (*fpData)(int, char *);

int* (*fpData)(int, int *, char *);

int* (*fpData)(int , char, int (*paIndex)[3]);

int* (*fpData)(int , int (*paIndex)[3] , int (* fpMsg) (const char *));

int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));

int* (*fpData[2])(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));

int* (*(*fpData)(const char *))(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));

 

 

Pointer and Structure:

We can also use the pointer with user-defined data types like structure and union. Let see a program to understand how we can use the pointer with structure. you can read the below article for more detailed information.

 

#include <stdio.h>
#include<string.h>
#include <stdlib.h>


// structure to store the information of book
typedef struct sBook
{
    char Name[20];
    char AuthorName[20];
    int PageNumber;
    int Price;

} sBook;



int main(int argc, char *argv[])
{

    sBook *psCBook = NULL; // create pointer to structure

    psCBook = malloc(sizeof(sBook)); // allocate memory to structure

    strcpy(psCBook->Name,"C world"); // copy the book name

    strcpy(psCBook->AuthorName,"Amlendra Kumar"); // copy author name

    psCBook->PageNumber = 1600; // assign number of page

    psCBook->Price = 1000; // Assign the price

    //Print the store data
    printf("Book Name = %s\n",psCBook->Name);

    printf("Book Author Name = %s\n",psCBook->AuthorName);

    printf("Book PageNumber = %d\n",psCBook->PageNumber);

    printf("Book Price = %d\n",psCBook->Price);

    // free the allocated memory

    free(psCBook);
    psCBook = NULL;


    return 0;
}

Output:

 

 

 

Pointers vs References in C++:

In C++  pointer and reference, both are used to access the object indirectly. So it is important to know when to use the pointer and when to use reference. You can check this article to know the difference between pointer and reference, “Printers vs References“.

 

Common mistakes with pointer

Let’s see some common mistakes with pointers which generally do by the newbie or freshers. You should be careful before using the pointers in your code because improper handling of the pointer might birth a bug that eats your multiple hours.

Uninitialized pointers in C:

An uninitialized pointer is very dangerous. It occurs when a programmer forgets to assign a valid memory before pointer use. The behavior of the uninitialized memory is undefined. Some people call it a wild pointer due to its behavior. Some smart compiler throws the warning for the uninitialized pointer.

Let’s see the below example:

#include <stdio.h>

int main(int argc, char *argv[])
{
    int *piData; // pointer to integer

    *piData =10;  // assining value to the pointer

    printf("Value %d\n",piData);

    return 0;
}

Output:

The behavior of this code is undefined.

 

Pointer comparison:

It becomes an issue when you will try to compare to the pointers that are pointing to the different memory blocks. See the below code snippet.

char acBuffer1[10] = “Hello”;
char acBuffer2[10] = “Bye”;
char *pc1, *pc2;
Assining the address of acBuffer1 to pc1 and acBuffer2 to the pc2.
pc1 = acBuffer1;
pc2 = acBuffer2;

//compare the both the pointer
if( pc1 > pc2) // illegal statement
{
}

 

Note: I have already discussed at the beginning of the article we can only compare the pointer if they are pointing to the same array.

 

Ilegal indirection:

In C language malloc function is used to allocate memory dynamically, on successful, it returns the beginning address of the allocated memory block. Sometimes we forget to remove the asterisk (*) symbol when assigning the address to the pointer. Let’s see the below example codes snippet.

char *pcBuffer = malloc(10); // Valid statement

 

But a mistake is in the below expression.

char *pcBuffer; 
*pcBuffer = malloc(10); // invalid statement

 

In the above statement, asterisk creates a problem. When we removed the asterisk the above statement becomes valid.

pcBuffer = malloc(10); // valid statement

 

A pointer pointing invalid address:

Generally, dangling pointers arise when the referencing object is deleted or deallocated, without changing the value of the pointers. It creates a problem because the pointer is still pointing to the memory that is not available. When the user tries to dereference the daggling pointers than it shows the undefined behavior and can be the cause of the program crash.

You can read the below article for more detail.

Let’s see some example code,

When you will compile the below code you will not get a compiler error but when you will run the code the behavior would be undefined.

Example code 1:

#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{
    int *piData = malloc(sizeof(int)); // pointer to integer

    free(piData); // free the allocated address

    *piData =10;  // Assining value to the pointer

    printf("Value %d\n",*piData);

    return 0;
}

 

Example code 2:

#include <stdio.h>

int * Calculate(int a, int b)
{
    int iData;

    iData = a+b;

    return &iData; //return the address of iData;
}

int main(int argc, char *argv[])
{
    int *piData = NULL; // pointer to integer

    piData = Calculate(4,5);

    printf("Value %d\n",*piData);

    return 0;
}

 

You can check, MCQs On Pointers in C/C++.

 

Recommended Post