Pointers are a core concept in C programming, yet can be a difficult concept to grasp for those who are new to the language.
And, here is my favourite question and answer regarding pointers:
> Q. Why are pointers used in C? > A. It's easier to give someone an address to your home than to give a copy of your home to everyone.
The rule to remember with pointer arithmetic is that a pointer will always increment by the size of the data type they are pointing to.
This is explained in the following example…
Arrays Decaying To Pointers
Consider the array:
&myArray is a pointer to the array. This pointers to the same memory address as just
myArray, which decays to a pointer to it’s first element. But, they have different types.
myArray is of type
&myArray is of type
&myArray + 1 points to the address after the end of the array, not the next element!
Really Good Articles On Pointers
Clever Uses Of Pointers
The following short piece of code:
is the equivalent to the standard library function
Strict Aliasing Rules
Be careful when performing “clever” pointer casting tricks to cast memory to different data types.
From section 6.5 of the C99 standard:
7. An object shall have its stored value accessed only by an lvalue expression that has one of the following types: - a type compatible with the effective type of the object, - a qualified version of a type compatible with the effective type of the object, - a type that is the signed or unsigned type corresponding to the effective type of the object, - a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object, - an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or - a character type.
Historically, these rules could be broken without too much worry. You could use pointer casting to access different representations of the same data by casting to different types. However, in modern compilers with optimisation turned on, this kind of code can cause fatal errors, because these rules allow them to assume that pointers to different types do not point to the same region (or an overlapping) region in memory, and once they assume that they can perform optimisations which will cause fatal errors if the pointers do infact point to the same region in memory.
Functions pointers are variables that rather than store a number or point to one, point to a function. They are commonly used for call-back routines and for function-based state machines. Function pointers can also be defined as a type.
Function Pointers On The 8051
Function pointers on 8051 architectures are dangerous. The 8051 has a tiny stack, and so variables passed into functions that are called indirectly have to be stored in registers. This limits you to a maximum of about 3 variables. If you exceed the maximum number of variables, you will get the “Indirect call: parameters do not fit into registers” error. To get around this you can use the reentrant keyword as shown below, which creates a “stack” for the variables in memory.
Using const And volatile With Pointers
When declaring pointers to objects that also need to be qualified as either
volatile, it can be hard to work out how to order the qualifiers.
Rule of thumb: Always place const and volatile qualifiers **AFTER** the thing you wish to make const of volatile.
For example, a constant
A pointer to a constant
A constant pointer to a
A constant pointer to a constant
The same applies for the
volatile keyword. For example, a
const pointer to a
volatile int would be written as:
This rule works in all situations. It also makes it easy to deduce the type of the variable, by reading backwards. For example, if you see:
int volatile * const x, you can deduce the type of
x by reading it backwards, e.g.
x is a
const * (pointer) to a
This work is licensed under a Creative Commons Attribution 4.0 International License .