¿Qué produciría esta declaración?
void *p = malloc(sizeof(void));
Editar: una extensión de la pregunta.
Si sizeof (void) produce 1 en el compilador GCC, entonces se asigna 1 byte de memoria y el puntero p apunta a ese byte y ¿se incrementaría p ++ a 0x2346? Suponga que p fuera 0x2345. Estoy hablando de p y no de * p.
c++
c
language-lawyer
sizeof
Lakshmi
fuente
fuente
Respuestas:
El tipo
void
no tiene tamaño; eso sería un error de compilación. Por la misma razón, no puede hacer algo como:void n;
EDITAR. Para mi sorpresa, hacer
sizeof(void)
realmente se compila en GNU C:$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc -w - && ./a.out 1
Sin embargo, en C ++ no:
$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc++ -w - && ./a.out <stdin>: In function 'int main()': <stdin>:1: error: invalid application of 'sizeof' to a void type <stdin>:1: error: 'printf' was not declared in this scope
fuente
sizeof (void)
es una violación de la restricción. Un compilador de C conforme (que gcc no es por defecto) debe al menos advertirlo y puede (y en mi humilde opinión debería) rechazarlo. Referencia: N1570 6.5.3.4p1 (void
es un tipo incompleto). Ha sido así desde el estándar de 1989, que se introdujovoid
.void
no existía antes de que fuera introducido por el estándar ANSI C de 1989, el mismo estándar quesizeof (void)
violaba las restricciones.Si está usando GCC y no está usando indicadores de compilación que eliminen las extensiones específicas del compilador, entonces
sizeof(void)
es 1. GCC tiene una extensión no estándar que hace eso.En general,
void
es un tipo incompleto y no puede usar sizeof para tipos incompletos.fuente
-Wpointer-arith
está implícita en-pedantic
. Siempre usé-pedantic
. :)Aunque
void
puede estar en el lugar de un tipo, en realidad no puede tener un valor. Por tanto, no tiene tamaño en la memoria. Obtener el tamaño de unvoid
no está definido.Un
void
puntero es simplemente una construcción del lenguaje que significa un puntero a la memoria sin tipo .fuente
void
no tiene tamaño. Tanto en C como en C ++, la expresiónsizeof (void)
no es válida.En C, citando N1570 6.5.3.4 párrafo 1:
(N1570 es un borrador de la norma ISO C de 2011).
void
es un tipo incompleto. Este párrafo es una restricción , lo que significa que cualquier compilador de C conforme debe diagnosticar cualquier violación del mismo. (El mensaje de diagnóstico puede ser una advertencia no fatal).El estándar C ++ 11 tiene una redacción muy similar. Ambas ediciones se publicaron después de que se hizo esta pregunta, pero las reglas se remontan al estándar ANSI C de 1989 y los primeros estándares C ++. De hecho, la regla que
void
es de un tipo incompleto a la quesizeof
no se puede aplicar se remonta exactamente a la introducción devoid
en el idioma.gcc tiene una extensión que se trata
sizeof (void)
como 1. gcc no es un compilador de C conforme de forma predeterminada, por lo que en su modo predeterminado no adviertesizeof (void)
. Se permiten extensiones como esta incluso para compiladores de C totalmente conformes, pero el diagnóstico aún es necesario.fuente
sizeof(void) == 1
coherencia con la aritmética delvoid
puntero en el puntero, que también es una extensión gcc . Citando de su documentación:A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.
. Pero aún así, el mensaje de diagnóstico debería estar presente de forma predeterminada para C, ya que estándar lo requiere.-std=c11 -pedantic
. Con tales opciones, emite el diagnóstico requerido.Tomar el tamaño del vacío es una extensión de GCC .
fuente
sizeof()
no se puede aplicar a tipos incompletos. Yvoid
es un tipo incompleto que no se puede completar.fuente
C ª,
sizeof(void) == 1
en GCC, pero esto parece depender de su compilador.En C ++, obtengo:
fuente
A la segunda parte de la pregunta: Note que sizeof (void *)! = Sizeof (void). En un arco de 32 bits, el tamaño de (void *) es de 4 bytes, por lo que p ++ se establecería en consecuencia. La cantidad en la que se incrementa un puntero depende de los datos a los que apunta. Entonces, se incrementará en 1 byte.
fuente
T*
se incrementa ensizeof(T)
(y nosizeof(T*)
, que casi siempre sería lo mismo, excepto quizás para punteros de función) cuando se incrementa. La excepción es, por supuestovoid
(y nuevamente la excepción es cuando se tienen habilitadas las extensiones GCC).void*
apunta un puntero es de 1 byte?sizeof (void)
es una violación de la restricción. (Una extensión de gcc lo trata como 1.)mientras que sizeof (void) quizás no tenga sentido en sí mismo, es importante cuando estás haciendo cualquier cálculo de puntero.
p.ej.
void *p; while(...) p++;
Si sizeof (void) se considera 1, esto funcionará. Si sizeof (void) se considera 0, entonces golpea un bucle infinito.
fuente
unsigned char*
.char
no se garantiza que sea de 1 byte. He trabajado en un sistema que lo puso en 32 bits.char
se garantiza que sea de 1 byte. Si ha trabajado en un sistema con 32 bitschar
, entonces un byte en ese sistema es de 32 bits (CHAR_BIT == 32
). Así es como el estándar C define "byte". C estándar, 6.5.3.4 párrafos 2 y 4: "Elsizeof
operador da el tamaño (en bytes) de su operando [...] Cuando.sizeof
Se aplica a un operando que tiene tipochar
,unsigned char
osigned char
, (o una versión calificada del mismo) el resultado es 1. "La mayoría de los compiladores de C ++ optaron por generar un error de compilación al intentar obtener
sizeof(void)
.Al compilar C, gcc no se ajusta y eligió definirlo
sizeof(void)
como 1. Puede parecer extraño, pero tiene una razón fundamental. Cuando hace aritmética de punteros, agregar o quitar una unidad significa agregar o quitar el objeto apuntado al tamaño. Por lo tanto, definirsizeof(void)
como 1 ayuda a definirvoid*
como un puntero a un byte (dirección de memoria sin escribir). De lo contrario, tendrías comportamientos sorprendentes usando aritmética de punteros comop+1 == p when
pvoid*
. Esta aritmética de punteros en punteros vacíos no está permitida en c ++ pero funciona bien cuando se compila C con gcc.La forma estándar recomendada sería utilizar
char*
para ese tipo de propósito (puntero a byte).Otra diferencia similar entre C y C ++ cuando se usa sizeof ocurre cuando define una estructura vacía como:
struct Empty { } empty;
Usar gcc como mi compilador de C
sizeof(empty)
devuelve 0. Usar g ++ el mismo código devolverá 1.No estoy seguro de qué establece los estándares C y C ++ en este punto, pero creo que definir el tamaño de algunas estructuras / objetos vacíos ayuda con la administración de referencias para evitar que dos referencias a objetos consecutivos diferentes, la primera vacía, obtengan el misma direccion. Si las referencias se implementan utilizando punteros ocultos como se hace a menudo, asegurarse de que haya direcciones diferentes ayudará a compararlos.
Pero esto es simplemente evitar un comportamiento sorprendente (comparación de casos de esquina de referencias) introduciendo otro (objetos vacíos, incluso los POD consumen al menos 1 byte de memoria).
fuente
sizeof(void)
no está definido en C, igual que en C ++. GCC simplemente no se ajusta a este punto, y la aritmética devoid
punteros en punteros tampoco está definida,void* p; p++;
no es válida. Incluso GCC le dará una advertencia al compilar con la-pedantic
bandera. Y también se equivoca sobre el comportamiento predeterminado de GCC para C ++: de forma predeterminada, esto se trata como un error .struct
definición vacía es un error de sintaxis; El soporte de gcc es una extensión. Pueden ser válidos en C ++; No estoy seguro.