Skip to main content

Pointers, Arrays & Strings - Part 1

This section covers the fundamentals of pointers in C, including pointer declaration, dereferencing, and basic string manipulation using pointers.

Understanding Pointers

A pointer is a variable that stores the memory address of another variable. Pointers are one of the most powerful features in C programming.

Pointer Basics

Syntax:
int *ptr;     // Pointer to an integer
char *str;    // Pointer to a character
Key Operators:
  • & - Address-of operator (gets the address of a variable)
  • * - Dereference operator (accesses the value at the address)

Function Prototypes

void reset_to_98(int *n);
void swap_int(int *a, int *b);
int _strlen(char *s);
void _puts(char *str);
void print_rev(char *s);
void rev_string(char *s);
void puts2(char *str);
void puts_half(char *str);
void print_array(int *a, int n);
char *_strcpy(char *dest, char *src);
int _atoi(char *s);

Pointer Dereferencing

reset_to_98()

Updates the value of an integer through a pointer.
void reset_to_98(int *n)
{
    *n = 98;
}
How it works:
  1. n is a pointer to an integer
  2. *n dereferences the pointer to access the actual value
  3. The value at the address is set to 98
Memory diagram:
Before:     After:
n points to → [45]    n points to → [98]
Always ensure pointers are initialized before dereferencing. Dereferencing a NULL or uninitialized pointer causes undefined behavior and crashes.

swap_int()

Swaps the values of two integers using pointers.
void swap_int(int *a, int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}
Example usage:
int x = 10, y = 20;
swap_int(&x, &y);
// Now: x = 20, y = 10
The & operator is used to pass the address of variables to the function, allowing modification of the original values.

String Manipulation with Pointers

In C, strings are arrays of characters terminated by a null byte (\0). Pointers provide an efficient way to traverse and manipulate strings.

_strlen()

Calculates the length of a string by incrementing a pointer.
int _strlen(char *s)
{
    int i;
    i = 0;
    while (*s != '\0')
    {
        i++;
        s++;
    }
    return (i);
}
Key concepts:
  • *s accesses the current character
  • s++ moves the pointer to the next character
  • Loop continues until null terminator (\0) is found

_puts()

Prints a string followed by a newline.
void _puts(char *str)
{
    while (*str != '\0')
    {
        _putchar(*str);
        str++;
    }
    _putchar('\n');
}
Process:
  1. Dereference pointer to get current character
  2. Print the character
  3. Move pointer to next position
  4. Repeat until null terminator

rev_string()

Reverses a string in place using array indexing.
void rev_string(char *s)
{
    int i, j;
    char temp;
    
    i = 0;
    j = 0;
    while (s[i] != '\0')
        i++;
    i--;
    while (i > j)
    {
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
        i--;
        j++;
    }
}
Algorithm:
  1. Find the length of the string
  2. Use two indices: one at start (j), one at end (i)
  3. Swap characters at these positions
  4. Move indices toward center
  5. Stop when indices meet
Example:
"hello" → "olleh"
Step 1: h ↔ o → "oellh"
Step 2: e ↔ l → "olleh"
Middle 'l' stays in place

String Copying

_strcpy()

Copies a string from source to destination.
char *_strcpy(char *dest, char *src)
{
    int i;
    
    for (i = 0; src[i] != '\0'; i++)
    {
        dest[i] = src[i];
    }
    dest[i] = '\0';
    return (dest);
}
Important points:
  • Copies all characters including the null terminator
  • Returns pointer to destination
  • Allows function chaining
The destination buffer must be large enough to hold the source string plus the null terminator. Buffer overflow can occur if dest is too small, leading to memory corruption.

Common Use Cases

Passing Arrays to Functions

void print_array(int *a, int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        printf("%d", a[i]);
        if (i < n - 1)
            printf(", ");
    }
    printf("\n");
}
Arrays decay to pointers when passed to functions, so int *a and int a[] are equivalent in function parameters.

Pointer Arithmetic

char str[] = "Hello";
char *ptr = str;

*ptr;       // 'H'
*(ptr + 1); // 'e'
*(ptr + 4); // 'o'
Pointer arithmetic automatically accounts for the size of the data type. ptr + 1 moves forward by sizeof(char) bytes.

Memory Safety Tips

  1. Always initialize pointers
    int *ptr = NULL;  // Good practice
    
  2. Check for NULL before dereferencing
    if (ptr != NULL)
        *ptr = 10;
    
  3. Don’t modify string literals
    char *str = "Hello";  // Read-only
    str[0] = 'h';         // ⚠️ Undefined behavior
    
    char str[] = "Hello"; // Modifiable
    str[0] = 'h';         // ✓ OK
    
  4. Array bounds checking
    char str[10];
    for (int i = 0; i < 10; i++)  // Good
        str[i] = 'A';
    

Key Takeaways

  • Pointers store memory addresses
  • Use & to get an address, * to dereference
  • Strings are character arrays ending with \0
  • Pointer arithmetic enables efficient string traversal
  • Always ensure buffers are large enough to prevent overflow
  • Initialize pointers before use to avoid undefined behavior

Build docs developers (and LLMs) love