¿Cuál es el tamaño del vacío?

¿Qué arrojaría esta afirmación?

void * p = (void*) malloc(sizeof(void)); 

Editar: una extensión de la pregunta.

Si sizeof (void) produce 1 en el comstackdor GCC, entonces se asigna 1 byte de memoria y el puntero p apunta a ese byte y p ++ se incrementará a 0x2346? Supongamos que p fuera 0x2345. Estoy hablando de p y no * p.

El tipo void no tiene tamaño; eso sería un error de comstackción. Por la misma razón, no puedes hacer algo como:

 void n; 

EDITAR. Para mi sorpresa, haciendo sizeof(void) realidad se comstack 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 : In function 'int main()': :1: error: invalid application of 'sizeof' to a void type :1: error: 'printf' was not declared in this scope 

Si está utilizando GCC y no está utilizando los indicadores de comstackción que eliminan las extensiones específicas del comstackdor, 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.

Aunque el void puede estar en su lugar para un tipo, en realidad no puede contener un valor. Por lo tanto, no tiene ningún tamaño en la memoria. Obtener el tamaño de un void no está definido.

Un puntero de void es simplemente una construcción de lenguaje que significa un puntero a la memoria sin tipo .

Tomar el tamaño del vacío es una extensión de GCC .

void no tiene tamaño. Tanto en C como en C ++, la expresión sizeof (void) no es válida.

En C, citando N1570 6.5.3.4 párrafo 1:

El operador sizeof no se aplicará a una expresión que tenga un tipo de función o un tipo incompleto , al nombre entre paréntesis de dicho tipo, o a una expresión que designe un miembro de campo de bit.

(N1570 es un borrador del estándar ISO C 2011).

void es un tipo incompleto. Este párrafo es una restricción , lo que significa que cualquier comstackdor de C conforme debe diagnosticar cualquier violación de él. (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 a los estándares más antiguos de C ++. De hecho, la regla de que el void es un tipo incompleto al cual sizeof puede no aplicarse se remonta exactamente hasta la introducción del void en el lenguaje.

gcc tiene una extensión que trata sizeof (void) ya que 1. gcc no es un comstackdor de C conforme por defecto, por lo que en su modo predeterminado no advierte sobre sizeof (void) . Extensiones como esta están permitidas incluso para comstackdores de C totalmente conformes, pero el diagnóstico aún es necesario.

sizeof() no se puede aplicar a tipos incompletos. Y el void es un tipo incompleto que no se puede completar.

En C, sizeof(void) == 1 en GCC, pero esto parece depender de tu comstackdor.

En C ++, obtengo:

 En la función 'int main ()':
 Línea 2: error: aplicación inválida de 'sizeof' a un tipo vacío
 comstackción terminada debido a -W fatal-errors.

A la segunda parte de la pregunta: Note que sizeof (void *)! = Sizeof (void). En un arco de 32 bits, sizeof (void *) tiene 4 bytes, por lo que p ++ se establecerá en consecuencia. La cantidad en que se incrementa un puntero depende de los datos a los que apunta. Por lo tanto, se incrementará en 1 byte.

mientras que sizeof (void) quizás no tenga sentido en sí mismo, es importante cuando está haciendo cualquier cálculo de puntero.

p.ej.

  void *p; while(...) p++; 

Si sizeof (void) se considera 1, entonces esto funcionará. Si sizeof (void) se considera 0, entonces usted golpea un bucle infinito.

La mayoría de los comstackdores C ++ eligieron generar un error de comstackción al intentar obtener sizeof(void) .

Al comstackr C, gcc no se ajusta y eligió definir sizeof(void) como 1. Puede parecer extraño, pero tiene un fundamento. Cuando se realiza una aritmética de puntero, agregar o eliminar una unidad significa agregar o eliminar el objeto que apunta al tamaño. Por lo tanto, la definición de sizeof(void) como 1 ayuda a definir void* como un puntero a byte (dirección de memoria sin tipo). De lo contrario, tendría comportamientos sorprendentes utilizando la aritmética del puntero como p+1 == p when p es void* . Tal aritmética de puntero en punteros vacíos no está permitida en c ++, pero funciona bien al comstackr C con gcc.

La forma estándar recomendada sería usar char* para ese tipo de propósito (puntero a byte).

Otra diferencia similar entre C y C ++ cuando se usa sizeof ocurre cuando se define una estructura vacía como:

 struct Empty { } empty; 

Usar gcc como mi comstackdor C sizeof(empty) devuelve 0. Usando 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 a evitar las dos referencias a diferentes objetos consecutivos, el primero está vacío, obtener el misma dirección. Si la referencia se implementa utilizando punteros ocultos como se hace a menudo, garantizar una dirección diferente ayudará a compararlos.

Pero esto es simplemente evitar un comportamiento sorprendente (comparación de casos de esquina de referencias) mediante la introducción de otro (objetos vacíos, incluso los POD consumen al menos 1 byte de memoria).