Using pointers in C

Pointers have to be one of the most difficult concepts to understand to new programmers. Although it’s relatively easy to use them, the main question still remains: why? I will show you how to create pointers in C-languages and why you can and should use them.

Memory
Every running application utilizes memory from your system. The larger the application, the higher the memory utilization. If you’re programming in any of the major system programming languages like C, C++, Objective-C, Java etc. you’ll need to allocate memory before you can use it. Scripting languages like Perl and PHP can do this for you. If you’re experienced in such a scripting language and now learning a system language, this concept might be new to you. In this tutorial I assume that you’ve studied some basic tutorials, and know how a basic C application would look like.

A typical C++ application:

#include <iostream>
using namespace std;
 
int main() {
     int myNumber;
     myNumber = 5;
     cout << "My number is "<< myNumber;
}

We have declared (reserved some space in memory) for an integer called ‘myNumber’ and assigned a number to it. The space is just as large as the maximum size that an integer can be in C;

Declaring Pointers
If we go back the previous example, we have declared an integer and named it ‘myNumber’. By appending a ‘&’ symbol to the variable name, we get the memory address of that space in memory, instead of its value;

int myNumber = 5;
// Show the value of myNumber
cout << myNumber;
 
// Show the memory address of myNumber
cout << &myNumber;

If I want to access the number through a 2nd name, I could just copy it like this:

int myNumber, myNumber2;
int myNumber = 5;
myNumber 2 = myNumber

We now have a copy, but we are utilizing twice the amount of space to hold the same number. If both variables should hold exactly the same number, there is a more efficient way of ‘sharing’ the value by using pointers. We tell the compiler we’re creating a pointer by appending an asterisk to it.

// A real variable
int myNumber;
 
// A pointer
int *myNumber2;
 
// Pointing the pointer to the address of the variable
myNumber2 = &myNumber;
 
// Getting the value of myNumber using either
cout << myNumber;
// or using
cout << *myNumber2;
 
// Getting the memory address of myNumber using either
cout << &myNumber;
// or using
cout << myNumber2;

To sum up what I’ve shown you in the above example:

– Get a variable value by using its name without any special characters.
– Get a pointer value by appending an asterisk (*) in front of the name.
– Get a variable address by appending an and (&) in front of the name.
– Get a pointer address by using its name without any special characters.

You can also memorize it like this: The purpose of a variable is holding the data, the purpose of a pointer is holding a memory address. Append a special character if you want the opposite behavior.

Why using pointers?
You might be thinking, do programmers actually need to share the contents of variables across different names? The answer is yes, in some situations you have to do this. It’s often used when creating arrays, and in an Objective-Oriented programming language like Objective-C it’s even required for it to function. Let’s assume you have a class in Objective-C called ‘CarManager’. It would look like this:

CarManager *car1 = [[CarManager alloc]init];

We are creating a new instance of the CarManager class and assigning it the unique name ‘car1’. Notice that this is a pointer? Why are we doing this? Let me explain:

When creating a new instance of a class it gets allocated a piece of memory and is then stored in it. We could theoretically do it all without assigning a name:

[[CarManager alloc]init];

The problem with this approach is that this instance does not have a unique name. Without a unique name we can’t give it any instructions because we can’t tell the compiler which instance we are trying to access. It also can’t be cleared from memory because of the same reason. Therefore we assign a name to it. Now it still might not be clear why we’re using a pointer. Let’s try to do it with a regular variable:

CarManager car1 = [[CarManager alloc]init];

In theory this would first assign memory and store an instance of the class in that space, and then it would copy that again to another space in memory. Basically you’d have two instances of the class, one that can be accessed with the unique name ‘car1’ and a second that can’t be accessed because it does not have a unique name. It’s the same difference between copying an application to your desktop and making a shortcut to it on your desktop.

Of course there is a failsafe system that prevents this from happening. Creating an instance of a class returns the memory address where it’s stored. So the variable ‘car1’ would only contain the memory address in plain text.

// This returns a memory address
[[CarManager alloc]init];
 
// Just like this
&myNumber;

Getting the picture? We need a shortcut pointing to each instance of a class. Each instance of a class returns its memory address when being declared. The only solution out of this one is using a pointer.

CarManager *car1 = [[CarManager alloc]init];

Conclusion
Pointers are very useful in some cases. Using Object-Oriented programming languages even require the use of pointers when working with objects. There are other uses of pointers, but they all come down to the same purpose: accessing parts in memory by a unique name without spoiling memory usage.

Leave a Reply

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