Conclusione finale: l'aritmetica su a void*è illegale sia in C che in C ++.
GCC lo consente come estensione, vedi Arithmetic on void- e Function-Pointers (nota che questa sezione fa parte del capitolo "C Extensions" del manuale). Clang e ICC probabilmente consentono l' void*aritmetica ai fini della compatibilità con GCC. Altri compilatori (come MSVC) non consentono l'aritmetica void*e GCC non lo consente se -pedantic-errorsviene specificato il -Werror-pointer-arithflag o se viene specificato il flag (questo flag è utile se la propria base di codice deve essere compilata anche con MSVC).
Lo standard C parla
Le citazioni sono tratte dalla bozza n1256.
La descrizione dello standard dell'operazione di aggiunta afferma:
6.5.6-2: Inoltre, entrambi gli operandi devono avere un tipo aritmetico oppure un operando deve essere un puntatore a un tipo di oggetto e l'altro deve avere un tipo intero.
Quindi, la domanda qui è se void*è un puntatore a un "tipo di oggetto", o equivalentemente, se voidè un "tipo di oggetto". La definizione di "tipo di oggetto" è:
6.2.5.1: I tipi sono suddivisi in tipi di oggetti (tipi che descrivono completamente gli oggetti), tipi di funzione (tipi che descrivono le funzioni) e tipi incompleti (tipi che descrivono gli oggetti ma mancano delle informazioni necessarie per determinarne le dimensioni).
E lo standard definisce voidcome:
6.2.5-19: il voidtipo comprende un insieme di valori vuoto; è un tipo incompleto che non può essere completato.
Poiché voidè un tipo incompleto, non è un tipo di oggetto. Pertanto non è un operando valido per un'operazione di aggiunta.
Pertanto non è possibile eseguire l'aritmetica del puntatore su un voidpuntatore.
Appunti
Inizialmente, si pensava che l' void*aritmetica fosse consentita, a causa di queste sezioni dello standard C:
6.2.5-27: Un puntatore a vuoto deve avere gli stessi
requisiti di rappresentazione e allineamento di un puntatore a un tipo di carattere.
Però,
Gli stessi
requisiti di rappresentazione e allineamento implicano l'intercambiabilità degli argomenti alle funzioni, restituiscono valori dalle funzioni e membri dei sindacati.
Quindi questo significa che printf("%s", x)ha lo stesso significato se xha tipo char*o void*, ma non significa che puoi fare l'aritmetica su a void*.
Nota del redattore: questa risposta è stata modificata per riflettere la conclusione finale.