Conclusión final: la aritmética en a void*
es ilegal tanto en C como en C ++.
GCC lo permite como una extensión, consulte Aritmética void
activada y Punteros de función (tenga en cuenta que esta sección es parte del capítulo "Extensiones C" del manual). Clang e ICC probablemente permitan la void*
aritmética para fines de compatibilidad con GCC. Otros compiladores (como MSVC) no permiten la aritmética activada void*
, y GCC no lo permite si -pedantic-errors
se especifica el indicador, o si -Werror-pointer-arith
se especifica el indicador (este indicador es útil si su base de código también debe compilar con MSVC).
El estándar C habla
Las citas están tomadas del borrador n1256.
La descripción del estándar de la operación de adición establece:
6.5.6-2: Además, ambos operandos deben tener un tipo aritmético o un operando debe ser un puntero a un tipo de objeto y el otro debe tener un tipo entero.
Entonces, la pregunta aquí es si void*
es un puntero a un "tipo de objeto", o de manera equivalente, si void
es un "tipo de objeto". La definición de "tipo de objeto" es:
6.2.5.1: Los tipos se dividen en tipos de objeto (tipos que describen completamente los objetos), tipos de función (tipos que describen funciones) y tipos incompletos (tipos que describen objetos pero carecen de la información necesaria para determinar sus tamaños).
Y el estándar define void
como:
6.2.5-19: El void
tipo comprende un conjunto vacío de valores; Es un tipo incompleto que no se puede completar.
Como void
es un tipo incompleto, no es un tipo de objeto. Por lo tanto, no es un operando válido para una operación de suma.
Por lo tanto, no puede realizar aritmética de puntero en un void
puntero.
Notas
Originalmente, se pensaba que la void*
aritmética estaba permitida, debido a estas secciones del estándar C:
6.2.5-27: Un puntero a anular tendrá los mismos
requisitos de representación y alineación que un puntero a un tipo de carácter.
Sin embargo,
Los mismos
requisitos de representación y alineación están destinados a implicar intercambiabilidad como argumentos de funciones, valores de retorno de funciones y miembros de sindicatos.
Esto significa que printf("%s", x)
tiene el mismo significado si x
tiene tipo char*
o void*
, pero no significa que pueda hacer aritmética en a void*
.
Nota del editor: esta respuesta ha sido editada para reflejar la conclusión final.