Pointer Arithmetic
Pointer arithmetic in the mikroC PRO for PIC32 is limited to:
- assigning one pointer to another,
- comparing two pointers,
- comparing pointer to zero,
- adding/subtracting pointer and an integer value,
- subtracting two pointers.
The internal arithmetic performed on pointers depends on the memory specifier in force and the presence of any overriding pointer modifiers. When performing arithmetic with pointers, it is assumed that the pointer points to an array of objects.
Arrays and Pointers
Arrays and pointers are not completely independent types in the mikroC PRO for PIC32.
When the name of an array comes up in expression evaluation (except with operators &
and sizeof
),
it is implicitly converted to the pointer pointing to array’s first element. Due to this fact, arrays are not modifiable lvalues.
Brackets [ ]
indicate array subscripts. The expression
id[exp]
is defined as
*((id) + (exp))
where either:
id
is a pointer andexp
is an integer, orid
is an integer andexp
is a pointer.
The following statements are true:
&a[i] = a + i a[i] = *(a + i)
According to these guidelines, it can be written:
pa = &a[4]; // pa points to a[4] x = *(pa + 3); // x = a[7] /* .. but: */ y = *pa + 3; // y = a[4] + 3
Also the care should be taken when using operator precedence:
*pa++; // Equal to *(pa++), increments the pointer (*pa)++; // Increments the pointed object!
The following examples are also valid, but better avoid this syntax as it can make the code really illegible:
(a + 1)[i] = 3; // same as: *((a + 1) + i) = 3, i.e. a[i + 1] = 3 (i + 2)[a] = 0; // same as: *((i + 2) + a) = 0, i.e. a[i + 2] = 0
Assignment and Comparison
The simple assignment operator (=
) can be used to assign value of one pointer to another if they are of the same type. If they are of different types, you must use a typecast operator. Explicit type conversion is not necessary if one of the pointers is generic (of the void
type).
Assigning the integer constant 0 to a pointer assigns a null pointer value to it.
Two pointers pointing to the same array may be compared by using relational operators ==
, !=
, <
, <=
, >
, and >=
. Results of these operations are the same as if they were used on subscript values of array elements in question:
int *pa = &a[4], *pb = &a[2]; if (pa == pb) {... /* won't be executed as 4 is not equal to 2 */ } if (pa > pb) {... /* will be executed as 4 is greater than 2 */ }
You can also compare pointers to zero value – testing in that way if the pointer actually points to anything. All pointers can be successfully tested for equality or inequality to null:
if (pa == 0) { ... } if (pb != 0) { ... }
Pointer Addition
You can use operators +
, ++
, and +=
to add an integral value to a pointer. The result of addition is defined only if the pointer points to an element of an array and if the result is a pointer pointing to the same array (or one element beyond it).
If a pointer is declared to point to type
, adding an integral value n
to the pointer increments the pointer value
by n * sizeof(type)
as long as the pointer remains within the legal range (first element to one beyond the last element).
If type
has a size of 10 bytes, then adding 5 to a pointer to type
advances the pointer 50 bytes in memory.
In case of the void
type, the size of a step is one byte.
For example:
int a[10]; /* array a containing 10 elements of type int */ int *pa = &a[0]; /* pa is pointer to int, pointing to a[0] */ *(pa + 3) = 6; /* pa+3 is a pointer pointing to a[3], so a[3] now equals 6 */ pa++; /* pa now points to the next element of array a: a[1] */
There is no such element as “one past the last element”, of course, but the pointer is allowed to assume such value. C “guarantees” that the result of addition is defined even when pointing to one element past array. If P
points to the last array element, P + 1
is legal, but P + 2
is undefined.
This allows you to write loops which access the array elements in a sequence by means of incrementing pointer — in the last iteration you will have the pointer pointing to one element past the array, which is legal. However, applying an indirection operator (*
) to a “pointer to one past the last element” leads to undefined behavior.
For example:
void f (some_type a[], int n) { /* function f handles elements of array a; */ /* array a has n elements of type some_type */ int i; some_type *p=&a[0]; for ( i = 0; i < n; i++ ) { /* .. here we do something with *p .. */ p++; /* .. and with the last iteration p exceeds the last element of array a */ } /* at this point, *p is undefined! */ }
Pointer Subtraction
Similar to addition, you can use operators -
, --
, and -=
to subtract an integral value from a
pointer.
Also, you may subtract two pointers. The difference will be equal to the distance between two pointed addresses, in bytes.
For example:
int a[10]; int *pi1 = &a[0]; int *pi2 = &a[4]; i = pi2 - pi1; /* i equals 8 */ pi2 -= (i >> 1); /* pi2 = pi2 - 4: pi2 now points to [0] */
What do you think about this topic ? Send us feedback!