2012-05-25 19 views
11
#include <stdio.h> 

int main() 
{ 
    printf("%d", sizeof(struct token *)); 
} 

El código anterior se puede compilar y vincular utilizar gcc en Linux. ¿Podría alguien de ustedes explicarme la cosa detrás de las escenas? Sé que el punto de tomar el tamaño fijo de la memoria, por lo que el token estructura es irrelevante para sizeof, pero incluso activar la opción de advertencia en gcc, "existen ninguno" no hay advertencias sobre la estructura en absoluto. El contexto de la cuestión es que estoy leyendo algo de código fuente por otros, estoy tratando muy, muy difícil de encontrar la definición de "señal struct", pero por supuesto no.¿por qué es posible utilizar estructura indefinida en c

+6

No es necesario 'token de struct 'para ser definido (ni siquiera declarado) para obtener el tamaño a un puntero a él. –

Respuesta

12

ya que están tratando de obtener el tamaño de un puntero a struct token. El tamaño de un puntero no depende de cómo se define realmente la estructura.

En general, incluso puede declarar una variable de tipo struct token*, pero no puede desreferenciarla (por ejemplo, acceder a un miembro a través del puntero).

+0

En C++, se puede declarar '' token de struct *, pero no se puede declarar '' símbolo *. No entiendo por qué el segundo no está permitido. Debido – Deqing

+0

sólo "token" no es un tipo incompleto, mientras que el "token de estructura" es, por lo que el compilador no puede reconocer "token" como un tipo. Piense en esto como solo una limitación sintáctica. –

9

Para parafrasear el estándar C, un tipo incompleto es un tipo que describe un objeto pero carece de la información necesaria para determinar su tamaño.

vacío es otro tipo incompleto. A diferencia de otros tipos incompletos, void no puede completarse .

Este "tipo incompleto" se utiliza a menudo para los tipos de mango: una biblioteca le permite asignar un "manejar" a algo, trabaja con él y disponer de nuevo. Todo esto sucede encapsulado en la biblioteca. Usted como usuario no tiene idea de lo que podría pasar dentro.

Ejemplo:

lib.h:

struct data * d_generate(void); 
void d_set(struct data *, int); 
int d_get(struct data *); 
void d_free(struct data*); 

lib.c:

#include "lib.h" 
#include <stdlib.h> 
struct data { int value; }; 
struct data * d_generate(void) { 
    return malloc(sizeof(struct data)) 
} 
void d_set(struct data * d, int v) { 
    d -> value = v; 
} 
int d_get(struct data * d) { 
    return d->value; 
} 
void d_free(struct data* d) { 
    free(d); 
} 

user.c:

#include "lib.h" 
[...] 
struct data * d = d_generate(); 
d_set(d, 42); 
int v = d_get(d); 
// but v = d->value; doesn't work here because of the incomplete definition. 
d_free(d); 
+1

Esto se conoce comúnmente como [tipo opaco] (http://en.wikipedia.org/wiki/Opaque_pointer#C) en C y se puede utilizar para lograr mecanismos orientados a objetos como encapsulación y polimorfismo. – Lundin

Cuestiones relacionadas