Skip to content

3.1 Basics

In C, pointers are variables that store memory addresses of other variables. Instead of holding data directly (such as integers or characters), a pointer holds the memory address where the data is stored. This allows for efficient manipulation of data, especially when working with dynamic memory, arrays, and complex data structures.

In C89, pointers are used in much the same way as they are in modern C, but there are some notable differences in terms of syntax and rules.

1. Pointers in C89

  1. Declaring a Pointer: A pointer is declared by specifying the type of data the pointer will point to, followed by an asterisk (*). For example:

    int *ptr;

    This declaration means ptr is a pointer to an integer. It does not contain an integer value itself but will store the memory address where an integer is located.

  2. Dereferencing a Pointer: Dereferencing a pointer means accessing the value stored at the memory location it points to. This is done using the asterisk (*) operator.

    int value = 10;
    int *ptr = &value;
    printf("%d", *ptr); // Outputs 10

    In this case, &value gives the address of value, and *ptr accesses the integer value stored at that address.

  3. Pointer Arithmetic: In C89, you can perform arithmetic operations on pointers, such as incrementing or decrementing them. This is often done with arrays, where a pointer can “move” through the elements.

    int arr[] = {1, 2, 3};
    int *ptr = arr;
    printf("%d", *ptr); // Outputs 1
    ptr++; // Move the pointer to the next element in the array
    printf("%d", *ptr); // Outputs 2
  4. Pointer to Pointer (Multilevel Pointers): In C89, you can have pointers that point to other pointers (i.e., “pointer to pointer”). This is often used in dynamic memory allocation or when dealing with arrays of strings.

    int value = 10;
    int *ptr = &value;
    int **ptr2 = &ptr;
    printf("%d", **ptr2); // Outputs 10
  5. Function Pointers: In C89, function pointers are used to store the address of a function. This is useful when you want to pass functions as arguments to other functions or implement callback mechanisms.

    void hello() {
    printf("Hello, world!\n");
    }
    int main() {
    void (*func_ptr)() = hello;
    func_ptr(); // Calls the hello() function
    return 0;
    }

2. Differences in C89

In terms of pointers, C89 introduced some specific practices and limitations that are different from later standards like C99 or C11. These include:

  1. Function Prototypes: C89 required all functions to be declared with prototypes, which defines the types of parameters and the return type before they are used. In earlier versions of C, function declarations could be omitted, which could lead to pointer-related issues due to mismatched function arguments.

    // C89-style function declaration
    int add(int a, int b);
  2. Pointer Type Compatibility: In C89, pointers are more strictly type-safe, which means that pointers of different types cannot be assigned to each other without an explicit cast. This is different from some behavior seen in C99 and later, where implicit conversions between some pointer types were allowed.

    // C89 requires a cast if assigning different pointer types
    int a = 10;
    void *ptr = &a; // This is allowed because `void *` is a generic pointer type
  3. No restrict Keyword: The restrict keyword, introduced in C99, tells the compiler that a pointer is the only way to access the object it points to. This helps the compiler optimize memory usage. Since restrict wasn’t available in C89, programmers had to rely on manual optimizations for pointer aliasing.

3. Example

Simple example in C89 that demonstrates basic pointer usage

#include <stdio.h>
int main() {
int value = 10;
int *ptr; // Declare a pointer to an integer
ptr = &value; // Store the address of 'value' in the pointer
printf("Value: %d\n", value); // Directly accessing 'value'
printf("Pointer points to value: %d\n", *ptr); // Dereferencing the pointer
// Pointer arithmetic
int arr[] = {1, 2, 3, 4};
int *arr_ptr = arr;
printf("First element: %d\n", *arr_ptr); // Outputs 1
arr_ptr++; // Move the pointer to the next element in the array
printf("Second element: %d\n", *arr_ptr); // Outputs 2
return 0;
}

4. Pointer Diagram

Pointers Image.