Pointer arithmetic for void pointer in C
CVoid PointersPointer ArithmeticC Problem Overview
When a pointer to a particular type (say int
, char
, float
, ..) is incremented, its value is increased by the size of that data type. If a void
pointer which points to data of size x
is incremented, how does it get to point x
bytes ahead? How does the compiler know to add x
to value of the pointer?
C Solutions
Solution 1 - C
Final conclusion: arithmetic on a void*
is illegal in both C and C++.
GCC allows it as an extension, see Arithmetic on void
- and Function-Pointers (note that this section is part of the "C Extensions" chapter of the manual). Clang and ICC likely allow void*
arithmetic for the purposes of compatibility with GCC. Other compilers (such as MSVC) disallow arithmetic on void*
, and GCC disallows it if the -pedantic-errors
flag is specified, or if the -Werror-pointer-arith
flag is specified (this flag is useful if your code base must also compile with MSVC).
The C Standard Speaks
Quotes are taken from the n1256 draft.
The standard's description of the addition operation states:
> 6.5.6-2: For addition, either both > operands shall have arithmetic type, > or one operand shall be a pointer to > an object type and the other shall > have integer type.
So, the question here is whether void*
is a pointer to an "object type", or equivalently, whether void
is an "object type". The definition for "object type" is:
> 6.2.5.1: Types are partitioned into object types (types that fully describe objects) , function types (types that describe functions), and incomplete types (types that describe objects but lack information needed to determine their sizes).
And the standard defines void
as:
> 6.2.5-19: The void
type comprises
> an empty set of values;
> it is an incomplete type that cannot
> be completed.
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.
Notes
Originally, it was thought that void*
arithmetic was permitted, because of these sections of the C standard:
> 6.2.5-27: A pointer to void shall have the same representation and alignment > requirements as a pointer to a > character type.
However,
> The same representation and alignment > requirements are meant to imply > interchangeability as arguments to > functions, return values from > functions, and members of unions.
So this means that printf("%s", x)
has the same meaning whether x
has type char*
or void*
, but it does not mean that you can do arithmetic on a void*
.
Solution 2 - C
Pointer arithmetic is not allowed on void*
pointers.
Solution 3 - C
cast it to a char pointer an increment your pointer forward x bytes ahead.
Solution 4 - C
The C standard does not allow void pointer arithmetic. However, GNU C is allowed by considering the size of void is 1
.
C11 standard §6.2.5
Paragraph - 19
> The void
type comprises an empty set of values; it is an incomplete
> object type that cannot be completed.
Following program is working fine in GCC compiler.
#include<stdio.h>
int main()
{
int arr[2] = {1, 2};
void *ptr = &arr;
ptr = ptr + sizeof(int);
printf("%d\n", *(int *)ptr);
return 0;
}
May be other compilers generate an error.
Solution 5 - C
You can't do pointer arithmetic on void *
types, for exactly this reason!
Solution 6 - C
Void pointers can point to any memory chunk. Hence the compiler does not know how many bytes to increment/decrement when we attempt pointer arithmetic on a void pointer. Therefore void pointers must be first typecast to a known type before they can be involved in any pointer arithmetic.
void *p = malloc(sizeof(char)*10);
p++; //compiler does how many where to pint the pointer after this increment operation
char * c = (char *)p;
c++; // compiler will increment the c by 1, since size of char is 1 byte.
Solution 7 - C
You have to cast it to another type of pointer before doing pointer arithmetic.
Solution 8 - C
Pointer arithmetic is not allowed in the void pointer.
Reason: Pointer arithmetic is not the same as normal arithmetic, as it happens relative to the base address.
Solution: Use the type cast operator at the time of the arithmetic, this will make the base data type known for the expression doing the pointer arithmetic. ex: point is the void pointer
*point=*point +1; //Not valid
*(int *)point= *(int *)point +1; //valid
Solution 9 - C
Compiler knows by type cast. Given a void *x
:
x+1
adds one byte tox
, pointer goes to bytex+1
(int*)x+1
addssizeof(int)
bytes, pointer goes to bytex + sizeof(int)
(float*)x+1
addressizeof(float)
bytes, etc.
Althought the first item is not portable and is against the Galateo of C/C++, it is nevertheless C-language-correct, meaning it will compile to something on most compilers possibly necessitating an appropriate flag (like -Wpointer-arith)