CPP

Pointers in C


Table of Contents

  1. What is a Pointer?
  2. Pointer Declaration and Initialization
  3. Pointer Operators
    • Address-of Operator (&)
    • Dereference Operator (*)
  4. Pointer Arithmetic
  5. Pointers and Arrays
  6. Strings in C++
  7. Pointers to Pointers
  8. Pointers and Functions
    • Passing Pointers to Functions
    • Returning Pointers from Functions
  9. Dynamic Memory Allocation
    • malloc, calloc, realloc, and free
  10. void * (Generic Pointers)
  11. NULL Pointer
  12. Common Pitfalls and Best Practices
  13. Conclusion

1. What is a Pointer?

A pointer is a variable that stores the memory address of another variable. Instead of holding a value directly, a pointer “points” to the location in memory where the value is stored.


2. Pointer Declaration and Initialization

Syntax

data_type *pointer_name;

Example

int x = 10;       // An integer variable
int *ptr;         // A pointer to an integer
ptr = &x;         // Assign the address of x to ptr

Here:


3. Pointer Operators

Address-of Operator (&)

The & operator is used to get the memory address of a variable.

int x = 10;
int *ptr = &x;  // ptr now holds the address of x

Dereference Operator (*)

The * operator is used to access the value stored at the memory address held by the pointer.

int x = 10;
int *ptr = &x;
cout << *ptr << endl;  // Output: 10

Here, *ptr gives the value stored at the address held by ptr, which is 10.


4. Pointer Arithmetic

Pointer arithmetic allows you to perform arithmetic operations on pointers. The operations are based on the size of the data type the pointer points to.

Example

int arr[] = {10, 20, 30};
int *ptr = arr;  // ptr points to the first element of arr

cout << *ptr << endl;  // Output: 10
ptr++;                 // Move to the next integer
cout << *ptr << endl;  // Output: 20

5. Pointers and Arrays

Arrays and pointers are closely related in C++. The name of an array is essentially a pointer to its first element.

Example

int arr[] = {10, 20, 30};
int *ptr = arr;  // ptr points to the first element of arr

cout << *(ptr + 1) << endl;  // Output: 20 (second element)
cout << arr[1] << endl;      // Output: 20 (same as above)

6. Strings in C++

In C++, a string is an array of characters terminated by a null character ('\0'). Strings are not a built-in data type in C but are represented using arrays of char and manipulated using pointers.

Declaring and Initializing Strings

char str1[] = "Hello";  // Automatically adds '\0' at the end
char str2[6] = {'H', 'e', 'l', 'l', 'o', '\0'};  // Manual null termination

Accessing Strings Using Pointers

Since strings are arrays, you can use pointers to manipulate them.

char *ptr = str1;  // ptr points to the first character of str1
cout << *ptr << endl;  // Output: H
cout << ptr << endl;   // Output: Hello

Common String Functions in C++

C++ provides a set of standard library functions for working with strings, declared in <cstring>.

Example:

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    char str1[] = "Hello";
    char str2[20];

    strcpy(str2, str1);  // Copy str1 to str2
    strcat(str2, " World");  // Concatenate " World" to str2

    cout << str2 << endl;  // Output: Hello World
    cout << "Length: " << strlen(str2) << endl;  // Output: 11
    return 0;
}

Write down an implementation for strlen. </br> Solution soln


7. Pointers to Pointers

A pointer can also point to another pointer. This is called a pointer to a pointer.

Syntax

data_type **pointer_name;

Example

int x = 10;
int *ptr = &x;   // ptr points to x
int **pptr = &ptr;  // pptr points to ptr

cout << **pptr << endl;  // Output: 10

8. Pointers and Functions

Passing Pointers to Functions

Passing pointers to functions allows you to modify the original variable directly.

void increment(int *ptr) {
    (*ptr)++;  // Increment the value at the address held by ptr
}

int main() {
    int x = 10;
    increment(&x);  // Pass the address of x
    cout << x << endl;  // Output: 11
    return 0;
}

by value vs by reference


void increment_byreference(int *ptr) {
    (*ptr)++;  
}
void increment_byvalue(int x) {
    (x)++; 
}

void increment_byreference2(int &x) {
    (x)++;  
}

int main() {
    int x = 10;
    increment_byreference(&x);   // incremented to 11
    increment_byvalue(x);  //stay 11
   increment_byreference2(x); // incremented to 12
    return 0;
}

Returning Pointers from Functions

Functions can also return pointers. Be careful to avoid returning pointers to local variables, as they go out of scope after the function returns.

int* createArray(int size) {
    int *arr = (int *)malloc(size * sizeof(int));
    return arr;
}

9. Dynamic Memory Allocation

Dynamic memory allocation allows you to allocate memory at runtime using functions like malloc, calloc, realloc, and free.

malloc

Allocates a block of memory of a specified size.

int *ptr = (int *)malloc(5 * sizeof(int));  // Allocate memory for 5 integers

calloc

Allocates memory and initializes it to zero.

int *ptr = (int *)calloc(5, sizeof(int));  // Allocate and initialize to 0

realloc

Resizes a previously allocated block of memory.

ptr = (int *)realloc(ptr, 10 * sizeof(int));  // Resize to 10 integers

free

Deallocates memory to avoid memory leaks.

free(ptr);  // Free the allocated memory

10. void * (Generic Pointers)

A void * is a generic pointer that can point to any data type. It is often used in functions that need to handle different types of data.

This section is from https://www.geeksforgeeks.org/void-pointer-c-cpp/

Example of Void Pointer in C

// C Program to demonstrate that a void pointer
// can hold the address of any type-castable type

#include <stdio.h>
int main()
{
    int a = 10;
    char b = 'x';

    // void pointer holds address of int 'a'
    void* p = &a;
    // void pointer holds address of char 'b'
    p = &b;
}

Properties of Void Pointers

1. Void pointers cannot be dereferenced.

Example

The following program doesn’t compile:

// C Program to demonstrate that a void pointer
// cannot be dereferenced

#include <stdio.h>
int main()
{
    int a = 10;
    void* ptr = &a;
    printf("%d", *ptr);

    return 0;
}

Output

Compiler Error: 'void*' is not a pointer-to-object type

The below program demonstrates the usage of a void pointer to store the address of an integer variable. The void pointer is typecasted to an integer pointer and then dereferenced to access the value. The following program compiles and runs fine.

// C program to dereference the void
// pointer to access the value

#include <stdio.h>

int main()
{
    int a = 10;
    void* ptr = &a;
    // The void pointer 'ptr' is cast to an integer pointer
    // using '(int*)ptr' Then, the value is dereferenced
    // with `*(int*)ptr` to get the value at that memory
    // location
    printf("%d", *(int*)ptr);
    return 0;
}

Output

10

2. The C standard doesn’t allow pointer arithmetic with void pointers.

However, in GNU C, it is allowed by considering the size of the void as 1.

Example

The below C program demonstrates the usage of a void pointer to perform pointer arithmetic and access a specific memory location. The following program compiles and runs fine in gcc.

// C program to demonstrate the usage
// of a void pointer to perform pointer
// arithmetic and access a specific memory location

#include <stdio.h>

int main()
{
    // Declare and initialize an integer array 'a' with two elements
    int a[2] = { 1, 2 };
    
    // Declare a void pointer and assign the address of array 'a' to it
    void* ptr = &a;

    // Increment the pointer by the size of an integer
    ptr = ptr + sizeof(int);

    // The void pointer 'ptr' is cast to an integer pointer
    // using '(int*)ptr'. Then, the value is dereferenced
    // with `*(int*)ptr` to get the value at that memory location
    printf("%d", *(int*)ptr);

    return 0;
}
**Output**  
2

11. NULL Pointer

A NULL pointer is a pointer that does not point to any valid memory location. It is often used to indicate that a pointer is not initialized or to mark the end of a data structure (e.g., a linked list).

Example

#include <iostream>
using namespace std;

int main() {
    int *ptr = NULL;

    if (ptr == NULL) {
        cout << "Pointer is NULL" << endl;  // Output: Pointer is NULL
    } else {
        cout << "Pointer is not NULL" << endl;
    }

    return 0;
}

12. Common Pitfalls and Best Practices


13. Conclusion

Pointers, strings, and memory management are fundamental concepts in C++ that allow you to write efficient and flexible programs. By mastering these concepts, you’ll be able to: