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
voidtype 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*.
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
voidtype 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*.
Pointer arithmetic is not allowed on void* pointers.
the program is running just fine without any warnings but the vscode IntelliSense is marking it as errors
int x[2] = { 3, 4 };
void *foo = &x;
void *boo = foo + 4;
printf("%d %d\n", *(int *)foo, *(int *)boo); // output: 3 4Is there a better way than casting to a char pointer?
No (except having a char * instead of a void * to begin with, so you don't have to cast it at all).
If this is not desirable or possible, then the only way is:
ptr = static_cast<char *>(ptr) + offset;
(Note: if you are doing this sort of stuff in C++, usually there is a much better solution. Unless you are an expert and you already ruled out every other alternative, I suggest you post a new question asking if there is a better way to do what you're trying to do!)
Take a look at this question, and this question. To summarise, the answer is to cast to char * for arithmetic at a byte level.
No this is not legal. A void* cannot be arbitrarily incremented. It needs to be cast to a specific type first.
If you want to increment it by a specific number of bytes then this is the solution I use.
p = ((char*)p) + 12;
The char type is convenient because it has a defined size of 1 byte.
EDIT
It's interesting that it runs on gcc with a warning. I tested on Visual Studio 2010 and verified it does not compile. My limited understanding of the standard would say that gcc in the error here. Can you add the following compilation flags
-Wall -ansi -pedantic
To quote from the spec:
§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. (Incrementing is equivalent to adding 1.)
A pointer to void is not a pointer to an object type, as per these excerpts:
§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).
§6.2.5/19: The void type comprises an empty set of values; it is an incomplete type that cannot be completed.
Therefore, pointer arithmetic is not defined for pointer to void types.