Pointers in C: What is Pointer in C Programming? Types

โšก Smart Summary

Pointers in C are variables that store the memory address of another variable. They enable dynamic memory allocation, efficient array and string handling, and complex data structures, using the address-of and dereference operators to read or modify values.

  • ๐Ÿ“Œ Definition: A pointer holds the memory address of another variable.
  • ๐Ÿ”ง Operators: The & operator returns an address; the * operator dereferences it.
  • ๐Ÿงท Declaration: Write data_type *name, then initialize with the address of a variable.
  • ๐Ÿท๏ธ Types: Null, void, and wild pointers behave differently and need care.
  • โž• Arithmetic: Incrementing a pointer moves it by the size of its base type.
  • ๐Ÿค– AI Assistance: AI tools debug segmentation faults and flag dangling pointers during review.

Pointers in C

What is a Pointer in C?

A pointer in C is a variable that stores the address of another variable. A pointer can also refer to another pointer or to a function. A pointer can be incremented or decremented to point to the next or previous memory location. The purpose of a pointer is to save memory space and achieve faster execution time.

How to Use Pointers in C

If we declare a variable v of type int, v stores a value. Each variable, apart from its value, also has an address, that is where it is located in memory. The address can be retrieved by putting an ampersand (&) before the variable name. If you print the address of a variable, it looks like a random number that can differ from run to run.

Instead of storing a value, a pointer stores the address of a variable. For example:

int *y = &v;
VARIABLE POINTER
A value stored in a named storage/memory address. A variable that points to the storage/memory address of another variable.

Declaring a Pointer

Like variables, pointers in C programming must be declared before they can be used. A pointer declaration has the following form:

data_type *pointer_variable_name;

Here, data_type is the pointer’s base type and indicates the type of the variable that the pointer points to. The asterisk (*), the same symbol used for multiplication, is the indirection operator that declares a pointer. Some valid pointer declarations are:

int    *ptr_thing;       /* pointer to an integer */
int    *ptr1, thing;     /* ptr1 points to an int; thing is an int */
double *ptr2;           /* pointer to a double */
float  *ptr3;           /* pointer to a float */
char   *ch1;            /* pointer to a character */

Initialize a Pointer

After declaring a pointer, we initialize it with a variable address. If a pointer is uninitialized and used, the results can be unpredictable and potentially disastrous. To get the address of a variable, use the ampersand (&) operator before the variable name:

pointer = &variable;

A simple program that illustrates a pointer is given below:

#include <stdio.h>
int main()
{
   int a = 10;     // variable declaration
   int *p;         // pointer variable declaration
   p = &a;        // store address of a in pointer p
   printf("Address stored in p is: %x\n", p);  // access the address
   printf("Value stored in p is: %d\n", *p);    // access the value
   return 0;
}

Output:

Address stored in p is: 60ff08
Value stored in p is: 10
Operator Meaning
* Serves two purposes: declares a pointer, and returns the value of the referenced variable (dereference).
& Serves one purpose: returns the address of a variable.

Types of Pointers in C

Null Pointer

We create a null pointer by assigning the value NULL during declaration. This is useful when no address is yet assigned to the pointer. A null pointer always contains the value 0:

#include <stdio.h>
int main()
{
   int *p = NULL;     // null pointer
   printf("The value inside variable p is: %x", p);
   return 0;
}

Void Pointer

A void pointer, also called a generic pointer, does not have any standard data type. It is created using the keyword void and can store the address of any variable:

#include <stdio.h>
int main()
{
   void *p = NULL;    // void pointer
   printf("The size of pointer is: %d\n", sizeof(p));
   return 0;
}

Wild Pointer

A pointer is called a wild pointer if it is not initialized to anything. These pointers are not efficient because they may point to an unknown memory location, which can cause problems and crash the program. Always be careful with wild pointers:

#include <stdio.h>
int main()
{
   int *p;          // wild pointer
   printf("%d", *p);
   return 0;
}

Other types of pointers in C include the dangling pointer, complex pointer, near pointer, far pointer, and huge pointer.

Direct and Indirect Access Pointers

In C, there are two equivalent ways to access and manipulate a variable’s content. Direct access uses the variable name directly, while indirect access uses a pointer to the variable:

#include <stdio.h>
int var = 1;        /* declare and initialize an int variable */
int *ptr;           /* declare a pointer to int */
int main(void)
{
   ptr = &var;       /* point ptr to var */
   printf("\nDirect access, var = %d", var);
   printf("\nIndirect access, var = %d", *ptr);
   *ptr = 48;        /* change var through the pointer */
   printf("\nIndirect access, var = %d", *ptr);
   return 0;
}

Pointer Arithmetic in C

When working with pointers, observe these priority rules. The operators * and & have the same priority as the unary operators (negation !, increment ++, decrement –). In the same expression, the unary operators *, &, !, ++, and — are evaluated from right to left. If a pointer P points to a variable X, then *P can be used wherever X can be written. The following expressions are equivalent:

Expression Equivalent Expression
Y = *P + 1 Y = X + 1
*P = *P + 10 X = X + 10
*P += 2 X += 2
++*P ++X
(*P)++ X++

In the last case, parentheses are required: because the unary operators * and ++ are evaluated from right to left, without parentheses the pointer P would be incremented, not the object it points to. The arithmetic operations available on pointers are assignment, increment and decrement, and adding or subtracting an integer offset, which moves the pointer by that many elements (each step equals the size in bytes of the base type).

C Pointers and Arrays with Examples

Traditionally, we access array elements using an index, but pointers make this easy too. A pointer set to the array name points to the first element:

#include <stdio.h>
int main()
{
   int a[5] = {1, 2, 3, 4, 5};   // array initialization
   int *p;                       // pointer declaration
   p = a;                       // p points to the first element; same as &a[0]
   for (int i = 0; i < 5; i++)
   {
      printf("%d\n", *p);            // print element
      p++;                      // move to the next element
   }
   return 0;
}

Adding a number to a pointer moves it that many elements forward. If p points to memory location 0, then p + 1 makes the pointer point to memory location 1.

C Pointers and Strings with Examples

A string is an array of char objects ending with a null character ‘\0’. We can manipulate strings using pointers:

#include <stdio.h>
#include <string.h>
int main()
{
   char str[] = "Hello Guru99!";
   char *p;
   p = str;
   printf("First character is: %c\n", *p);
   p = p + 1;
   printf("Next character is: %c\n", *p);
   p = str;                     // reset the pointer
   for (int i = 0; i < strlen(str); i++)
   {
      printf("%c\n", *p);
      p++;
   }
   return 0;
}

Another way to deal with strings is with an array of pointers:

#include <stdio.h>
int main()
{
   char *materials[] = {"iron", "copper", "gold"};
   for (int i = 0; i < 3; i++)
      printf("%s\n", materials[i]);
   return 0;
}

Advantages of Pointers in C

  • Pointers are useful for accessing memory locations directly.
  • They provide an efficient way to access the elements of an array.
  • They are used for dynamic memory allocation and deallocation.
  • They are used to form complex data structures such as linked lists, graphs, and trees.

Disadvantages of Pointers in C

  • Pointers are a little complex to understand.
  • They can cause errors such as segmentation faults or access to an unintended memory location.
  • An incorrect value given to a pointer may cause memory corruption.
  • Pointers are also responsible for memory leaks if memory is not freed.
  • It is the programmer’s responsibility to handle a pointer carefully.

FAQs

A dangling pointer points to memory that has been freed or is out of scope. Avoid it by setting the pointer to NULL immediately after calling free, and checking for NULL before use.

Dereferencing a NULL pointer causes a segmentation fault and crashes the program at run-time. Always check that a pointer is not NULL before using the * operator to read or write.

A double pointer, declared as int **pp, stores the address of another pointer. It is used for dynamic 2D arrays and to modify a pointer argument inside a function.

A pointer stores a memory address, and addresses are the same width on a given platform, typically 4 bytes on 32-bit and 8 bytes on 64-bit, regardless of the type it points to.

A function pointer stores the address of a function so it can be called dynamically. It is widely used for callbacks and for building tables of functions selected at run-time.

Functions like malloc and calloc return a pointer to memory allocated on the heap at run-time. You access that memory through the pointer and release it with free to avoid leaks.

Yes. AI assistants read a segmentation fault and the surrounding code, then explain the likely cause, such as an uninitialized or freed pointer, and suggest a fix for you to review.

AI-powered analyzers, alongside tools like Valgrind, flag memory that is never freed and pointers used after free. They automate review and highlight risky patterns before the code ships.

Summarize this post with: