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*
.