Pointer in C Programming: Types, Examples and Uses

Pointer in C Programming Types, Examples and Uses

Pointers are one of the most important concepts in C programming because they allow a program to work with memory addresses directly. They are commonly used with arrays, functions, structures, dynamic memory, and low-level programming.

For beginners, the confusing part is usually the difference between a variable’s value, its address, and the pointer that stores that address.

Once this relationship is clear, pointers become much easier to understand.

A pointer in C programming is a variable that stores the address of another object or function. The & operator can be used to obtain an object’s address, while the * operator can be used to access the value stored at the address held by a pointer.

For example:

int number = 25;

int *ptr = &number;

printf(“%d”, *ptr);

Here:

  • number stores 25.
  • &number gives the address of number.
  • ptr stores that address.
  • *ptr accesses the value stored at that address.

So, *ptr gives 25.

What Is a Pointer in C Programming?

A pointer is a variable whose value is an address.

Consider an ordinary integer variable:

c
int number = 25;

The variable number stores the value 25 somewhere in memory. We can obtain its address using the address-of operator:

c
&number

A pointer can then store that address:

c
int *ptr = &number;

The relationship can be viewed simply as:

number
  |
  | stores 25
  ↓
[ 25 ]

ptr
  |
  | stores address of number
  ↓
[ address of number ]

The pointer does not normally store the value 25 itself. It stores information about where number is located.

C pointers can point to objects, functions, or have a null pointer value indicating that they do not point to an object or function.

registor_now_P

How Do Pointers Work in C?

Pointers work through two fundamental operations:

  • Getting an address
  • Dereferencing an address

1. Getting an Address

The & operator returns the address of an object.

c
int age = 28;

printf("%p", (void *)&age);

&age represents the address of age.

2. Dereferencing a Pointer

The * operator can be used to access the object pointed to by a pointer.

c
int age = 28;
int *ptr = &age;

printf("%d", *ptr);

Output:

28

The pointer ptr contains the address of age, while *ptr accesses the value stored in age. The C language defines pointer indirection as a way to access the object referred to by a pointer.

Declaration of a Pointer in C

The basic syntax for pointer declaration is:

c
data_type *pointer_name;

For example:

c
int *ptr;
float *price;
char *letter;

The data type tells C what type of object the pointer is intended to point to. For example:

c
int *ptr;

means ptr is a pointer to int.

You can also declare multiple pointers:

c
int *p1, *p2;

Both p1 and p2 are pointers to int.

A common beginner mistake is writing:

c
int *p1, p2;

Here, only p1 is a pointer. p2 is an ordinary int variable. C’s declaration syntax treats the * as part of the declarator, so each pointer variable needs its own *.

Initialization of a Pointer in C

Declaring a pointer and giving it a valid address are two different things. For example:

c
int *ptr;

declares the pointer but does not give it the address of a valid int object.

A safer initialization is:

c
int number = 50;
int *ptr = &number;

Now ptr points to number.

You can also initialize a pointer to the null pointer value:

c
int *ptr = NULL;

A null pointer indicates that the pointer does not currently point to an object or function.

Why initialize a pointer?

An uninitialized automatic pointer may contain an indeterminate value. Dereferencing such a pointer can result in undefined behavior. Therefore, initialize a pointer with a valid address or an appropriate null pointer value before using it.

How to Use Pointers in C

A simple example shows the basic use clearly:

c
#include 

int main(void)
{
    int number = 25;
    int *ptr = &number;

    printf("Value: %d\n", number);
    printf("Address: %p\n", (void *)&number);
    printf("Pointer value: %p\n", (void *)ptr);
    printf("Value through pointer: %d\n", *ptr);

    return 0;
}

The important relationship is:

number  →  25
ptr     →  address of number
*ptr    →  25

You can also modify the original variable through the pointer:

c
int number = 25;
int *ptr = &number;

*ptr = 40;

printf("%d", number);

Output:

40

Changing *ptr changes number because ptr refers to number.

Pointer Operators in C

Two operators are particularly important when learning pointers.

OperatorPurposeExample
&Gets the address of an object&number
*Dereferences a pointer*ptr

For example:

c
int number = 10;
int *ptr = &number;

Here:

  • &number → address of number
  • ptr → stores that address
  • *ptr → value at that address

The * symbol has different meanings depending on context. In a declaration such as int *ptr, it indicates a pointer type. In an expression such as *ptr, it performs indirection.

What Are the Types of Pointers in C?

Pointers can be classified according to what they point to or how they are used.

1. Integer Pointer

c
int number = 10;
int *ptr = &number;

ptr points to an integer.

2. Character Pointer

c
char letter = 'A';
char *ptr = &letter;

ptr points to a character.

3. Float Pointer

c
float value = 12.5f;
float *ptr = &value;

ptr points to a floating-point value.

4. Pointer to Pointer

A pointer can also store the address of another pointer.

c
int number = 10;
int *ptr = &number;
int **pptr = &ptr;

The relationship is:

pptr → ptr → number

pptr is therefore a pointer to a pointer to int.

5. Void Pointer

A void * can hold a pointer to an object of any object type and is commonly used in generic interfaces such as those involving dynamic memory and library functions.

Example:

c
int number = 10;
void *ptr = &number;

Before dereferencing a void *, it needs to be used with the appropriate object type.

6. Function Pointer

A function pointer stores the address of a function. For example:

c
int add(int a, int b)
{
    return a + b;
}

int (*operation)(int, int) = add;

The function can then be called through the pointer:

c
int result = operation(10, 20);

Function pointers are useful for callbacks and selecting functions dynamically.

7. Null Pointer

A null pointer does not point to an object or function.

c
int *ptr = NULL;

It is often used to represent “no valid object” or “no target.”

Explore Courses - Learn More

Pointer Arithmetic in C

Pointer arithmetic is particularly useful when working with arrays.

Suppose:

c
int numbers[] = {10, 20, 30, 40};
int *ptr = numbers;

Here, ptr points to the first element. You can move to the next element:

c
ptr++;

Now ptr points to the next int. You can also use:

c
printf("%d", *(ptr + 2));

This accesses the third element.

The important point is that pointer arithmetic is based on the pointed-to type. For a pointer to an array element, adding 1 moves to the next element rather than simply adding one byte. Pointer arithmetic is defined within the same array object, including the one-past-the-end position.

For example:

c
int numbers[4] = {10, 20, 30, 40};

int *ptr = numbers;

printf("%d\n", *ptr);       // 10
printf("%d\n", *(ptr + 1)); // 20
printf("%d\n", *(ptr + 2)); // 30

This is one reason pointers and arrays are closely connected in C.

Pointers and Arrays

In many expressions, an array name is converted to a pointer to its first element.

For example:

c
int numbers[3] = {10, 20, 30};

int *ptr = numbers;

Here, ptrnumbers[0]. So:

c
*ptr

accesses numbers[0]. And:

c
*(ptr + 1)

accesses numbers[1].

You can therefore process an array using a pointer:

c
#include 

int main(void)
{
    int numbers[] = {10, 20, 30, 40};

    int *ptr = numbers;

    for (int i = 0; i < 4; i++)
    {
        printf("%d\n", *(ptr + i));
    }

    return 0;
}

Pointers to arrays are a related but different concept from arrays of pointers. Parentheses matter when declaring more complex pointer types. For example:

c
int (*p)[3];

is a pointer to an array of three integers.

Pointers and Functions

One of the most useful applications of pointers is passing an object’s address to a function.

Consider:

c
void update(int *value)
{
    *value = 100;
}

It can be called as:

c
int number = 20;

update(&number);

After the function call:

number = 100

The function receives the address of number, allowing it to modify the original object. This technique is commonly used when a function needs to modify caller-owned data or work with arrays and structures.

Pointers and Structures

Pointers are also widely used with structures.

Consider:

c
struct Student
{
    int age;
    float marks;
};

You can create a structure and a pointer to it:

c
struct Student student = {21, 85.5f};
struct Student *ptr = &student;

Members can be accessed through the pointer using the -> operator:

c
printf("%d", ptr->age);

This is equivalent to:

c
printf("%d", (*ptr).age);

The -> operator makes structure pointers much easier to work with.

Size of a Pointer Variable in C

The size of a pointer is implementation-dependent. It should not be assumed that every pointer is 4 bytes or every pointer is 8 bytes.

You can determine the size on the current implementation using sizeof:

c
int *ptr;

printf("%zu", sizeof(ptr));

sizeof returns the size of an object or type in bytes as a value of type size_t.

For example, a particular system might use 8-byte object pointers, while another implementation may use a different size. Therefore, avoid writing code that assumes:

c
sizeof(pointer) == 8

unless the target platform explicitly guarantees it.

Also remember that the size of a pointer is not the size of the object it points to. For example:

c
int number = 10;
int *ptr = &number;

sizeof(ptr) gives the size of the pointer, while sizeof(number) gives the size of the int object.

Applications of Pointers in C

Pointers are especially important in low-level and systems-oriented C programming.

Common applications include:

  • Passing data to functions by address
  • Processing arrays efficiently
  • Working with strings
  • Dynamic memory management
  • Building linked lists, trees, and other data structures
  • Accessing structure members
  • Implementing callbacks with function pointers
  • Working with buffers
  • Interacting with hardware and memory-mapped resources in embedded systems
  • Writing operating-system and device-level software

In embedded C, pointers are particularly important because firmware often needs to work with buffers, peripheral registers, memory addresses, and hardware interfaces. However, pointer use must follow the rules of the C implementation and the target hardware. An arbitrary address should never be treated as automatically safe to access.

Advantages and Limitations of Using Pointers in C

Pointers provide powerful capabilities, but they also require careful handling.

Advantages

  • Allow functions to modify caller-owned objects.
  • Make array and buffer processing flexible.
  • Support dynamic data structures.
  • Enable dynamic memory management.
  • Allow function callbacks through function pointers.
  • Provide the low-level memory access needed by many systems and embedded programs.

Limitations

Incorrect pointer handling can cause:

  • Segmentation faults or other runtime failures
  • Undefined behavior
  • Memory corruption
  • Use-after-free bugs
  • Buffer overflows
  • Dangling pointers
  • Difficult-to-debug program errors

The power of pointers comes with responsibility: the pointer must refer to a valid object or otherwise be used according to the applicable C rules.

Common Mistakes When Working With Pointers in C

1. Dereferencing an Uninitialized Pointer

Avoid:

c
int *ptr;
*ptr = 10;

ptr has not been given a valid target.

Instead:

c
int number;
int *ptr = &number;

*ptr = 10;

2. Dereferencing a Null Pointer

Avoid:

c
int *ptr = NULL;

printf("%d", *ptr);

A null pointer does not point to a valid object.

3. Using a Pointer After Its Target Is No Longer Valid

For example, after dynamically allocated memory has been released, retaining and dereferencing the old pointer can create a dangling-pointer problem.

4. Accessing Outside an Array

For:

c
int numbers[3] = {10, 20, 30};

this is not valid:

c
printf("%d", numbers[3]);

The valid indexes are 0, 1, and 2. Pointer arithmetic has similarly strict boundaries. Going outside the permitted array range can result in undefined behavior.

5. Confusing *ptr with ptr

Consider:

c
int number = 25;
int *ptr = &number;

Here:

  • ptr → address
  • *ptr → value

Mixing these two concepts is one of the most common beginner errors.

6. Assuming All Pointers Have the Same Size

Pointer size depends on the implementation and target architecture. Use sizeof when the actual size is needed.

Talk to Academic Advisor

Conclusion

A pointer is simply a variable that holds an address instead of a direct value – the rest of what makes pointers feel difficult is really about being careful with that address: initializing it, checking it before use, and releasing it correctly when it points to dynamically allocated memory. Once declaration, initialization, and dereferencing feel natural, concepts like function pointers, double pointers, and register-level access in embedded C stop being separate hurdles and start looking like the same idea applied in different contexts.

FAQs

Use the pointer declaration syntax:

int *ptr;

This declares ptr as a pointer to an int.

You can initialize a pointer with the address of a compatible object:

int number = 10;

int *ptr = &number;

You can also initialize it to NULL when it currently has no valid target.

Common pointer types include pointers to integers, characters, structures, arrays, functions, pointers to pointers, void * pointers, and null pointers.

There is no single size guaranteed for all systems. Pointer size depends on the implementation and target architecture. sizeof(pointer) can be used to determine the size on the current implementation.

Pointers provide direct access to objects through their addresses and support important C programming techniques such as array processing, modifying objects through functions, dynamic memory management, data structures, callbacks, and low-level programming.

Author

Embedded Systems and IOT Trainer– IIES

Updated On: 010-08-26


10+ years of hands-on experience delivering practical training in Embedded Systems and it's design