Pointer arithmetic for void pointer in 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 bothoperands shall have arithmetic type,or one operand shall be a pointer toan object type and the other shallhave 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 comprisesan empty set of values;it is an incomplete type that cannotbe 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 alignmentrequirements as a pointer to acharacter type.
However,
The same representation and alignmentrequirements are meant to implyinterchangeability as arguments tofunctions, return values fromfunctions, 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*
.
cast it to a char pointer an increment your pointer forward x bytes ahead.