Pointers in C

Reading Time: 2 minutes

Pointers


C provides an extremely nice way to access memory via pointer variables. The declaration looks like the following

void *var;

The asterisk before the variable denotes that it’s a pointer variable. A pointer variable stores address of some memory location, typically a variable or a newly allocated memory area.

We know how to declare arrays, let’s take a look at how we can use pointers to traverse the array. We’ll be using a character array and a pointer to a character to traverse the array.

 

 

  1. int main() {
  2. char str[] = "Hello World";
  3. char *str2 = str;
  4.  
  5. while (*str2 != '\0')
  6.     printf("%c", *str2++);
  7.  
  8. return 0;
  9. }

In the above code, we’ve created a character array and then assigned a pointer to it’s base address. The while condition checks the value at the address contained in pointer variable for being null.

Since the array is fixed we can’t really move the base address however what we can do is move the pointer variable around. That’s what we do in the printf statement.

Pointers and References

C++ allows us to have references which work mostly like pointers however there’s a very basic and subtle difference. Pointers are first class variables that is they have their own memory location where an address can be stored, while references don’t have their own memory location.

Thus references can’t be uninitialised pointers can be since they are first class variables. This is shown in the table below

SyntaxDescription
void *ptr = NULL;Valid since ptr will have it's own memory location.
int &ref;Invalid since references aren't allocated separate memory location.

It's just another name for an already existing variable.

Generic Pointers

A pointer always points to some type at a location. However sometimes it’s necessary to write code where the pointer variable required is generic, i.e any type. This is achieved by creating a void pointer

Sizeof a pointer variable

The pointer variable is always fixed in size and it’s size is machine’s word size. The machine’s word size is denoted by the data type long. This fact is very important since it helps us creating data types that references themselves. For example, while the following piece of code is correct

struct linked_list {
struct linked_list *next;
void *data;
};
This one is not.. 
struct linked_list {
struct linked_list next;
void *data;
};
Since we can’t create a variable before a definition is complete as the size won’t be known to compiler however we can always create a pointer even to incomplete types

Pointer Arithmetic

Pointers like other variables can be used for some arithmetic operations however not all arithmetic operations are valid for pointers. For example the following table shows what all arithmetic are possible

SyntaxDescription
ptr + constantAddition of a constant to a pointer.
ptr - constantSubtraction of a constant from a pointer variable.
ptr + non_pointer_variable Addition of a non-pointer variable to a pointer
ptr - non_ptr_variable Subtraction of non-pointer variable from a pointer.
ptr1 - ptr2Subtraction of 2 pointers.

All other arithmetic operations like division / multiplication  involving pointer variables isn’t allowed.

Addition/Subtraction involving pointers

When a value is decremented or incremented from a pointer variable the pointer is incremented or decremented by the size of type of value the pointer points to. For example

SyntaxDescription
char *ptr = 0x1234;
ptr = ptr +1
Moves ptr to location 0x1235
short *ptr = 0x1234;
ptr += 1;
Moves ptr to location 0x1236, since adding 1 moves to the next of the type pointed to by ptr.
int *ptr = 0x1234;
ptr += 1;
Moves ptr to 0x1238, i.e next int which is 4 bytes away from initial location.
int *ptr = 0x1234;
long *ptr_long = 0x1234;
ptr - ptr_long;
This is invalid since the type of pointers being decremented must be pointing to same type.

Reading pointer declarations

The general rule of reading pointer declarations is to start from the pointer variable and then move to right and then move to left building up the declaration. We’ll start with simpler ones

SyntaxDescription
int *ptr;Start from the variable, move to right.
We find a delimiter so move to left.
We see a * thus it becomes ptr is a pointer
we continue moving to left and find int, thus
ptr is a pointer to int
char *ptr[];Start with ptr and move to right, we see [], so
ptr is an array
Next move to left and we find a *, it becomes
ptr is an array of pointers
we continue moving left and find char thus,
ptr is an array of pointers to char
char (*ptr[])();From previous example, we see that ptr is an array of pointers however,
we've to stop whenever we see a paranthesis. The parenthesis to the right denotes function therefore,
ptr is an array of pointers to function then we move left and see char
ptr is an array of pointers to function returning char

const char *ptr;
ptr is a pointer to const character.
That is the pointer can be changed but the value it points to can't.

char *const ptr;
Again using the same rule,
ptr is a constant pointer to a character
That is to the value can change but the pointer variable can't be changed
i.e. it always points to fixed variable.
The following table describes some neat tricks with pointers.

Pointer Tricks

SyntaxDescription
*ptr++Give the value first then increment pointer.
*++ptrIncrement the pointer first then give the value from the new location.
(*ptr)++Increment the value pointed to by ptr. The pointer itself isn't incremented.

 

Leave a Reply