How to Use Pointers in C: Avoiding Errors and Increasing Efficiency

You know the saying, “With great power comes great responsibility.” You may have thought it only applied to Presidents or other “important” people, but I think it applies to us programmers as well. Especially when we’re coding in C and using pointers. Pointers are powerful, which makes them both useful and dangerous. If you’re not exactly sure when and where you should implement them, you’re not alone. Their primary purpose is to make your programs run more efficiently, especially when dealing with large arrays. The problem is that if you don’t use them properly you can cause memory leaks or even corrupt your storage.

What Are Pointers?

As their name would suggest, pointers point to things. They’re a variable that stores an address which points to the memory location of another variable. That means you can access a variable through its address, rather than calling it like you normally would. Pointers are also used in C to allow arrays and strings.

Usually, if I want to utilize a variable in my code I’ll just call it. That variable is then copied into the call stack and I can use it. When I employ a pointer to grab a variable the operation is a little different. Instead of copying the variable into my function, the pointer’s value is copied and then used to access the variable. This might seem like semantics, but I’ll get to why it’s important soon.

In addition to accessing memory addresses, pointers allow you to initialize structs or arrays. In fact, arrays in C are actually just constant pointers that indicate where a series of values are stored in memory. Likewise, strings in C are considered to be arrays and are thus really pointers as well.

Pointers let you directly access data stored in memory.

When to Use Pointers

On the surface, you may not think pointers are very useful. They point to a memory address, so what? However, they can be used to make your code much more efficient, especially when dealing with large arrays or data structures.

Remember earlier I said that when I call a variable in C it’s copied into the function? That isn’t a big deal for most variables as they’re relatively small. However, what if I have a huge variable or an array of variables that take up lots of memory? We all have limited amounts of memory, and calling values from memory takes energy, so I don’t want to have to copy all those values if I don’t have to. Pointers allow us to call an array, or edit values in an array without copying it into the call stack. When you use a pointer to access an array or data inside of an array the function merely copies the value of the pointer into the call stack. So you can operate on large variables or arrays much more efficiently using pointers.

One example of pointer use is in vehicles with advanced driver assistance systems (ADAS). Advanced cars often use a range of sensors that are all supplying data at different intervals. C allows you to organize that data into structures to sort the different types of data. Since an ADAS enabled vehicle will have many sensors, though, you can even create an array of structures to deal with all the information. Just like with a normal array, pointers can then be used to operate on a specific structure type or a value within a structure. Again, using pointers in this way can simplify your code and make it run more efficiently. Many researchers and companies have struggled to create low power memory; don’t negate that work by inefficiently accessing it.

Be careful how you use pointers or you might end up with a memory leak.

How to Use Pointers

Pointers are powerful because they allow you to directly access memory addresses. This same usefulness also makes them very dangerous. If you don’t use your pointers correctly you can access garbage data or leave them dangling. Another product of incorrect usage is memory leaks.

When you initialize a pointer in C the values that it is pointing to remain the same. This means if a pointer is referencing garbage data and you use it before you write over that data, your program will use those meaningless values. This is an easy fix, all you have to do is initialize your pointers to null so that they don’t point to anything. Dangling pointers usually happen in one of two ways. The memory that the pointer was indicating is freed or de-allocated or the variable goes out of scope and the memory location becomes invalid. In the first case, after deallocating memory, you should return that pointer to null, so that it isn’t left dangling. To avoid letting your pointers reference out of scope variables you can make those variables static.

One major issue that can stem from dangling pointers is a memory leak. This happens when you allocate memory using a pointer, and then reassign or delete that pointer without freeing the memory that was originally allocated. That piece memory then becomes “lost” and cannot be accessed again. This leak could continue happening, causing your program to run out of memory and crash. The best way to mitigate this risk is to always free the memory before deleting or changing your pointer. Memory leaks are difficult to track down, especially in large programs, so be sure to make this a habit and avoid losing a leak in thousands of lines of code.

Pointers are just variables that point to other variables and can help you make your code more efficient. They’re particularly useful in applications like ADAS vehicles where you need to parse many different types of data coming in from tens of sensors. The problem is that if you use them correctly they can cause your program to crash. Avoid dangling pointers and memory leaks using the tips in this article and you’ll be able to use pointers without regret.