Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A raw pointer in C++ is a fundamental data type that stores the direct memory address of an object, function, or block of memory. Unlike smart pointers introduced in C++11, raw pointers do not implement ownership semantics or automatic resource management, leaving the developer strictly responsible for memory allocation, deallocation, and lifetime tracking.

Syntax and Indirection

A raw pointer is declared using the asterisk (*) operator appended to a type. The address-of operator (&) is used to retrieve the memory address of an existing variable, while the dereference operator (*) accesses the value stored at the pointer’s memory address.
int value = 42;
int* ptr = &value;       // Declaration: ptr stores the memory address of 'value'
int dereferenced = *ptr; // Dereference: retrieves the value 42 from the address
*ptr = 100;              // Mutates 'value' directly through the pointer

Null Pointers

A pointer that does not point to any valid memory location should be explicitly initialized to a null state. In modern C++, nullptr is the type-safe standard for representing a null pointer literal, replacing the legacy NULL macro or integer 0.
int* uninitializedPtr;         // Wild pointer: contains garbage memory address (undefined behavior)
int* safePtr = nullptr;        // Points to nothing, safe to evaluate in conditionals

if (safePtr != nullptr) {
    // Safe to dereference
}

Void Pointers (void*)

A void* is a generic raw pointer type used to store the memory address of any data type, effectively providing type erasure. Because the compiler lacks information about the size or type of the underlying data, a void* cannot be directly dereferenced and does not support pointer arithmetic. It must be explicitly cast back to a typed pointer (typically using static_cast) before the memory can be accessed.
int value = 42;
void* genericPtr = &value; // Type erasure: int* implicitly converts to void*

// int deref = *genericPtr; // Invalid: Compilation error (cannot dereference void*)
int* typedPtr = static_cast<int*>(genericPtr);
int deref = *typedPtr;      // Valid: Evaluates to 42

Dynamic Memory Management

Raw pointers are the primary mechanism for interacting with heap-allocated memory via the new and delete operators. Because raw pointers lack destructors that clean up their target memory, failing to call delete results in a memory leak.
// Single object allocation
int* dynamicInt = new int(50); 
delete dynamicInt;             // Frees the allocated memory
dynamicInt = nullptr;          // Mitigates dangling pointer risk

// Array allocation
int* dynamicArray = new int[10];
delete[] dynamicArray;         // Array-specific deallocation operator is required

Pointer Arithmetic

Raw pointers support arithmetic operations (+, -, ++, --). The arithmetic is scaled by the sizeof the underlying data type. If an int is 4 bytes, incrementing an int* increases the underlying memory address by 4 bytes, not 1 byte.
int buffer[3] = {10, 20, 30};
int* ptr = buffer;             // Decays to pointer to first element (&buffer[0])

ptr++;                         // Advances memory address by sizeof(int)
int secondValue = *ptr;        // Evaluates to 20

int offsetValue = *(ptr + 1);  // Evaluates to 30 without mutating 'ptr'

Const Qualifiers

The const keyword modifies pointer behavior depending on its placement relative to the asterisk (*). While the C++ compiler parses these declarations using standard left-to-right grammar rules (declaration specifiers followed by declarators), the semantic effect is determined by whether const applies to the pointed-to type or the pointer itself. (A common human mnemonic is to read the declaration from right to left, though this is not how the compiler operates).
int target = 10;
int otherTarget = 20;

// 1. Pointer to const data (Data is immutable, address is mutable)
const int* ptrToConst = &target;
ptrToConst = &otherTarget;     // Valid
// *ptrToConst = 15;           // Invalid: Compilation error

// 2. Const pointer (Address is immutable, data is mutable)
int* const constPtr = &target;
*constPtr = 15;                // Valid
// constPtr = &otherTarget;    // Invalid: Compilation error

// 3. Const pointer to const data (Both address and data are immutable)
const int* const strictPtr = &target;

Multiple Indirection

Raw pointers can point to other pointers, creating multiple levels of indirection. This requires matching the declaration depth with the appropriate number of asterisks.
int value = 99;
int* ptr = &value;             // Level 1: Points to int
int** ptrToPtr = &ptr;         // Level 2: Points to int*
int*** ptrToPtrToPtr = &ptrToPtr; // Level 3: Points to int**

int resolved = ***ptrToPtrToPtr;  // Dereferenced three times to yield 99

Function Pointers

Raw pointers can also store the memory address of executable code (functions) rather than data. The syntax requires specifying the function’s return type and parameter signature. The pointer name and its preceding asterisk must be enclosed in parentheses to ensure correct operator precedence; otherwise, the compiler interprets it as a function returning a pointer.
int add(int a, int b) { 
    return a + b; 
}

// Declaration: pointer to a function taking two ints and returning an int
int (*funcPtr)(int, int) = &add; 

// Invocation via function pointer
int result = funcPtr(5, 10); // Evaluates to 15
Master C++ with Deep Grasping Methodology!Learn More