Cuando un puntero a un tipo particular (por ejemplo int
, char
, float
, ..) se incrementa, su valor se incrementa el tamaño de ese tipo de datos. Si se incrementa un void
puntero que apunta a datos de tamaño x
, ¿cómo llega a apuntar x
bytes por delante? ¿Cómo sabe el compilador agregar x
valor al puntero?
c
pointers
void-pointers
pointer-arithmetic
Siva Sankaran
fuente
fuente
void
puntero que apunta a datos de tamañox
, ¿cómo llega a apuntarx
bytes por delante?" No lo hace. ¿Por qué las personas que tienen esas preguntas no pueden evaluarlas antes de preguntar? Ya saben, al menos al mínimo, donde verifican si realmente se compila, lo cual no es así. -1, no puedo creer que esto haya obtenido +100 y -0.Respuestas:
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 lavoid*
aritmética para fines de compatibilidad con GCC. Otros compiladores (como MSVC) no permiten la aritmética activadavoid*
, 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:
Entonces, la pregunta aquí es si
void*
es un puntero a un "tipo de objeto", o de manera equivalente, sivoid
es un "tipo de objeto". La definición de "tipo de objeto" es:Y el estándar define
void
como: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:Sin embargo,
Esto significa que
printf("%s", x)
tiene el mismo significado six
tiene tipochar*
ovoid*
, pero no significa que pueda hacer aritmética en avoid*
.Nota del editor: esta respuesta ha sido editada para reflejar la conclusión final.
fuente
void*
aritmética de punteros no está permitida. GCC tiene una extensión que permite hacer esto.void*
aritmética (al menos por defecto).La aritmética de puntero no está permitida en
void*
punteros.fuente
void
es un tipo incompleto que nunca se puede completar por definición.póngalo en un puntero char e incremente su puntero adelante x bytes adelante.
fuente
char
, el incrementox
y la reinterpretación del nuevo valor como algún otro tipo es un comportamiento inútil e indefinido.man 3 qsort
debería tener lavoid qsort(void *base, size_t nmemb, size_t size, [snip])
, entonces no tiene forma de conocer el "tipo correcto"El estándar C no permite la aritmética de puntero vacío . Sin embargo, GNU C está permitido considerando el tamaño de vacío es decir
1
.Norma C11 §6.2.5
Párrafo - 19
El siguiente programa funciona bien en el compilador GCC.
Puede haber otros compiladores que generen un error.
fuente
No puede hacer aritmética de puntero en
void *
tipos, ¡exactamente por esta razón!fuente
Debe lanzarlo a otro tipo de puntero antes de hacer la aritmética del puntero.
fuente
Los punteros vacíos pueden apuntar a cualquier fragmento de memoria. Por lo tanto, el compilador no sabe cuántos bytes aumentar / disminuir cuando intentamos la aritmética del puntero en un puntero vacío. Por lo tanto, los punteros vacíos deben primero ser encasillados a un tipo conocido antes de que puedan participar en cualquier aritmética de puntero.
fuente
Compilador sabe por tipo de reparto. Dado un
void *x
:x+1
agrega un byte ax
, el puntero va al bytex+1
(int*)x+1
agregasizeof(int)
bytes, el puntero va al bytex + sizeof(int)
(float*)x+1
direccionessizeof(float)
bytes, etc.Aunque el primer elemento no es portátil y está en contra del Galateo de C / C ++, sin embargo, es correcto para el lenguaje C, lo que significa que se compilará en algo en la mayoría de los compiladores que posiblemente necesiten un indicador apropiado (como -Wpointer-arith)
fuente
Althought the first item is not portable and is against the Galateo of C/C++
Cierto.it is nevertheless C-language-correct
Falso. ¡Esto es doble pensamiento! La aritmética del punterovoid *
es sintácticamente ilegal, no debe compilarse y produce un comportamiento indefinido si lo hace. Si un programador descuidado puede compilarlo deshabilitando alguna advertencia, eso no es excusa.unsigned char*
por ejemplo, para agregar unsizeof
valor a un puntero.