In C/C++, addition or subtraction on pointer is defined only if the resulting pointer lies within the original pointed complete object. Moreover, comparison of two pointers can only be performed if the two pointed objects are subobjects of a unique complete object.
What are the reasons of such limitations?
I supposed that segmented memory model (see here §1.2.1) could be one of the reasons but since compilers can actually define a total order on all pointers as demonstrated by this answer, I am doubting this.
Using pointer in C programming has following disadvantages: If pointers are referenced with incorrect values, then it affects the whole program. Memory leak occurs if dynamically allocated memory is not freed. Segmentation fault can occur due to uninitialized pointer.
Pointer arithmetic provides the programmer with a single way of dealing with different types: adding and subtracting the number of elements required instead of the actual offset in bytes. (Pointer arithmetic with char * pointers uses byte offsets, because sizeof(char) is 1 by definition.)
Advantage of Use Pointers: Pointers are more efficient in handling arrays and data tables. Pointers can be used to return multiple values from a function. Pointers permit references to functions and thus allow passing functions as arguments to other functions.
Since void is an incomplete type, it is not an object type. Therefore it is not a valid operand to an addition operation. Therefore you cannot perform pointer arithmetic on a void pointer.
The reason is to keep the possibility to generate reasonable code. This applies to systems with a flat memory model as well as to systems with more complex memory models. If you forbid the (not very useful) corner cases like adding or subtracting out of arrays and demanding a total order on pointers between objects you can skip a lot of overhead in the generated code.
The limitations imposed by the standard allows the compiler to make assumptions on pointer arithmetic and use this to improve quality of the code. It covers both computing things statically in the compiler instead of at runtime and choosing which instrutions and addressing modes to use. As an example, consider a program with two pointers p1
and p2
. If the compiler can derive that they point to different data objects it can safely assume that any no operation based on following p1
will ever affect the object pointed to by p2
. This allows the compiler to reorder loads and stores based on p1
without consider loads and stores based on p2
and the other way around.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With