ANSI C Pointers 101

Standard

Hi, I believe that Pizza and The C Programming Language are two of the most awesome things in the Universe. Also, I have a thesis:  The Universe was created by Morgan Freeman using just ANSI C code and Pizza, think about it! (I’m quite sure that Neil deGrasse Tyson has already done it). Celebrating this spiritual belief I’ll explain some very essential rules that govern our reality (#SpoilerAlert: I’ll talk about Pointers in C) in a basic but really different way.

The key concepts served in this post are:

  1. The use of pointers to manipulate variables.
  2. The use of pointers to access the elements of an array.
  3. The use of pointers to cast data across different data types.

As you might already imagine I’ll dish up these ideas with the magic of a crispy crust, tomato sauce and a lot of cheese (#OhYeah). But before we begin, I’ll expect from you a basic knowledge about C (mainly data types, variables and functions). O.K. lets go!

1. The use of pointers to manipulate variables

Variables are used to store data and perform different kinds of operations. In some cases we share them across our code as arguments in functions. C functions have two ways to pass arguments: by value or by reference. A by value argument is a copy of the variable’s value. Modifying the copie’s value has no effect in the original variable. Here’s a by value argument function example, where foo is a function that receives the argument a.

#include 
void foo(int a){
  a = 30;
}
void main(){
  int a = 2;
  foo(a);
  printf("The variable is equal to: %d\n", a);
}

The program’s result will be the message: The variable is equal to: 2. The function foo changed the value of the local variable a, and the main function’s variable a suffered no changes. Now imagine a pair of friends (lets say Jessy and Mr. White) in a Pizza place. Jessy asks for two slices of the astonishing “Pepperoni and Bacon” pizza, and gives one to Mr. White. Even though both have a slice from the same pizza, they have different slices. Mr. White’s slice won’t be modified while Jessy is eating his own pizza slice.

Now, passing a variable by reference is a different story. You do this by using Pointers. Every time you use pointers, a baby seal is been saved from the evil hands of fishermen heartless monsters. A pointer in ANSI C references a memory location i.e. the place where something is stored in principal memory. Changing a variable’s value from a pointer will directly alter the variable’s value, since we’re in the same place. Here’s a by reference argument function example that receives a pointer to a variable.

#include 
void foo(int *a){
  *a = 30;
}
int main(){
  int a = 2;
  foo(&a);
  printf("The variable is equal to: %d\n", a);
 
  return 0;
}

The main function will print: The variable is equal to: 30. Now, picture Jessy and Mr. White holding the same pizza slice. If one of them take a bite from it, both will see the change in the pizza slice. This is because they’ll be holding the same slice. That’s how pointers roll!

 

2. The use of pointers to access the elements of an array

Since C pointers are memory references, we can implement a pointer to access the elements of a static array. We just have to point to the beginning of the array, after that you’re ready to go. Take a look at the next example, here we move over a static array and print each of its elements. We have to indicate the starting point of the memory and the total elements in the array.

#include 
void printElements(int *pointer, int len){
  int i;
 
  for(i = 0; i < len; i++){
    printf("The element at the position %d is: %d\n", i, pointer[i]);
  }
}
int main(){
  int array [5] = {1, 2, 3, 4, 5};
  printf("The array size is: %lu\n", sizeof(array));
 
  printElements(&array[0], sizeof(array)/sizeof(int));
 
  return 0;
}

So, according to what’s explained above we need two things: the memory’s starting point and the number of items in the array. The instruction &array[0] points out the origin of the array‘s memory space. Also, sizeof(array) indicates how many bytes does the array occupy (Yup!, literally the sizeof). We get the number of items dividing the total bytes of the memory by the amount of bytes required for the data type. The example illustrates an array of ints, therefore we use sizeof(int). Then we can travel across the memory. It’s like if our friend Jessy were holding the pizza pan of a marvellous pizza from the beginning. Jessy will have access to the whole pizza array and he’ll be able to access every slice in the pan. Also Jessy can take a slice by indicating how many places he’ll have to move from your reference point (i.e. pointer[places]). Then Jessy would say to Mr. White: Yo! Want some pizza, b*tch!?

 

3. The use of pointers to cast data across different data types

This is probably my favourite property of pointers. You can manipulate the variable on a byte level basis taking advantage of how’s the variable located in memory, it’s a combination of the two concepts explained before. For example, lets look at the next example.

#include 
void printElements(char *pointer, int len){
  int i;
 
  for(i = 0; i < len; i++)
    printf("The value at %d has the value of: %d\n", i, pointer[i]);
}
int main(){
  int number = 1;
  char *pointer = (char *)&number;
  printf("The value is: %d\n", number);
 
  pointer[0] = 0;
  pointer[1] = 1;
  printf("The value is: %d\n", number);
 
  printElements((char *)&number, sizeof(int));
  return 0;
}

Here is an example of how we can manipulate a int variable with a char pointer. An int data type is four byte long and is arranged in memory as a four contiguos bytes. Once we point to the start of this memory, we can iterate through it. But, to do this we have to chose the proper data type. In the example, we choose a char pointer (char data types are one byte long) to manipulate every byte in the int data type. The code above will print out the next:

The value is: 1
The value is: 256
The value at 0 has the value of: 0
The value at 1 has the value of: 1
The value at 2 has the value of: 0
The value at 3 has the value of: 0

Picture yourself in front of a Pizza with extra Pepperoni and extra Bacon. You take a slice of pizza from the pan, and you realize that it’s actually a pair of slices (#HonestMistake). Now you can manage two slices of pizza; change the ingredients from one slice to the other, eat the slices separately, put ketchup only on one of them. It’s like if we say to them (In Jessy’s words) “Yo! I’ll make you my b*tch!”.

Well, that’s all for today folks! Maybe some other time we’ll discuss about dynamic memory (of course in C). Hope you enjoyed the article and by now you’re eating pizza. Comments are greatly appreciated.

Leave a Reply

Your email address will not be published. Required fields are marked *