¿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
voidno 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 1Sin 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 scopefuente
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 (voides un tipo incompleto). Ha sido así desde el estándar de 1989, que se introdujovoid.voidno 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,
voides un tipo incompleto y no puede usar sizeof para tipos incompletos.fuente
-Wpointer-arithestá implícita en-pedantic. Siempre usé-pedantic. :)Aunque
voidpuede 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 unvoidno está definido.Un
voidpuntero es simplemente una construcción del lenguaje que significa un puntero a la memoria sin tipo .fuente
voidno 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).
voides 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
voides de un tipo incompleto a la quesizeofno se puede aplicar se remonta exactamente a la introducción devoiden 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) == 1coherencia con la aritmética delvoidpuntero 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. Yvoides un tipo incompleto que no se puede completar.fuente
C ª,
sizeof(void) == 1en 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*.charno se garantiza que sea de 1 byte. He trabajado en un sistema que lo puso en 32 bits.charse 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: "Elsizeofoperador da el tamaño (en bytes) de su operando [...] Cuando.sizeofSe aplica a un operando que tiene tipochar,unsigned charosigned 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 whenpvoid*. 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 devoidpunteros en punteros tampoco está definida,void* p; p++;no es válida. Incluso GCC le dará una advertencia al compilar con la-pedanticbandera. Y también se equivoca sobre el comportamiento predeterminado de GCC para C ++: de forma predeterminada, esto se trata como un error .structdefinició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.