Pointers in Embedded C- Explained

Embedded C for microcontrollers

In this article, we go over what pointers are and how we can code them in C for embedded applications.

What is a Pointer?

Pointers are variables that contain the address or location of a variable, constant, function, or data object.

So a pointer isn't the actual data. It simply represents the address or location of the data that is being referenced.

How to Code pointers in C

A variable is declared to be a pointer with the indirection or dereferencing operator, *:

char *p; //here p is a pointer to a character
int *fp; //here fp is a pointer to an integer

The pointer data type allocates an area in memory large enough to hold the machine address of the variable. For example, the address of a memory location in a typical microcontroller will be described in 16 bits. So in a typical microcontroller, a pointer to a character will be a 16-bit value, even though the character itself it only an 8-bit value.

Once a pointer is declared, you are now dealing with the address of the variable it is pointing to, not the value of the variable itself. You must think in terms of locations and contents of locations. The address operator (&) is used ot gain access to the address of a variable. This address may be assigned to the pointer and is the pointer's value. The indirection or deferencing operator (*) is used to gain access to the data located at the address contained in the pointer.

char *p; //p is a pointer to a character. No character has been chosen yet
char a, b; //2 characters, a and b, have been declared
p = &a; //p is now pointing to a
b= *p; //the location pointed to by p (which is a) is assigned to b

In this example, p is assigned to the address of a, so p is pointing to a. Now in order to get the value at this adress located at a, the indirection operator (*) is used. In the following line, the value at address a is obtained and stored into b.

What Pointers Are Used For

Pointers are an excellent method of accessing a peripheral in a system, such as an I/I port. For instance, if we had an 8-bit parallel output port located at 0x1010 in memory, that port could be accessed through indirection as follows:

unsigned char *out_port; //declares out_port as a pointer
out_port= 0x1010; //assign out_port with the address value
*out_port= 0xaa; //this assigns a value to the address

So here we create a pointer called out_port. Then we assign the address of this out_port to be 0x1010. Then we assign an actual data value to this address, 0xaa.

Since pointers are effectively addresses, they offer the ability to move, copy, and change memory in all sorts of ways with very little instruction. So address arithmetic can be done pretty easily. When it comes to performing address arithmetic, the C compiler makes sure that the proper address is computed based on the type of variable or constant being addressed.

For example,

int *ptr;
long *lptr;

ptr= ptr+1;//moves the pointer to the next integer (2 bytes away)

lptr= lptr+1; //moves the pointer to the next long integer (4 bytes away)

ptr and lptr are incremented by one location, which in reality is 2 bytes for ptr and 4 bytes for lptr, because of their subsequent types. This is also true for the increment and decrement operations, shown below:

ptr++; //moves the pointer to the next integer location (2 bytes)
--lptr; //moves the pointer back to the preceding long integer location (4 bytes)

Since the indirection (*) and address (&) operators are unary operators and are at the highest precedence, they will always have priority over the other operations in an expression. Since increment and decrement are also unary operators and share the same priority, expressions containing these operators will be evaluated from left to right.

HTML Comment Box is loading comments...