Chapter 23. Memory Addresses and Pointers

Virtually every value used in a program is stored in memory and has a memory address.

We sometimes need to use the memory address of a variable instead of the data it contains. For example, the Fortran read subroutine and the C scanf() function both need to know the memory address of a variable in order to place input data in it.

Since Fortran passes arguments by reference, Fortran subprograms naturally know the address of all the arguments passed to them.

Since C passes arguments by value, we need to explicitly pass the address of a variable to any function that needs to know it.

if ( scanf("%d %d", &rows, &cols) != 2 )
    

So how to functions like scanf() make use of the addresses passed to them?

They use pointer variables. A pointer variable is a variable that contains a memory address rather than data.

We can assign a pointer variable the address of any other variable of the appropriate data type. We can then access the data in the variable pointed to using what is called indirection.

int     rows = 2,
	cols = 3;
int     *ptr;       // Holds the address of an int variable

ptr = &rows;
printf("%d\n", *ptr);  // Indirect access to the value in rows, prints 2

ptr = &cols;
printf("%d\n", *ptr);  // Indirect access to the value in cols, prints 3
    

Functions that need to modify a variable in the caller must know the address of that variable. We've already seen that we can pass the address from the caller using the & operator:

scanf("%d %d", &rows, &cols);
    

To receive such an address in the function, we simply define the argument as a pointer. Consider the simple task of swapping the values of two variables:

temp = first;
first = second;
second = temp;
    

We might try to implement this as a function for convenience:

void    swap_ints(int first, int second)

{
    int     temp;
    
    temp = first;
    first = second;
    second = temp;
}

swap(a, b);
    

Knowing that C passes arguments by value, however, makes it apparent that this function is useless. The argument variables first and second are at different memory addresses than a and b, so swapping them has no effect on a and b.

In order to create a working swap function, we need to define the argument variables as pointers and pass the addresses of the arguments:

void    swap_ints(int *first, int *second)

{
    int     temp;
    
    temp = *first;
    *first = *second;
    *second = temp;
}

swap(&a, &b);
    

Pointer variables have many additional uses, but their primary purpose in scientific programming is for passing addresses of data to functions.