2009-03-09 29 views
21

EDITAR: aparentemente algo de esto no está permitido/ha cambiado en varios estándares de C. Para mi propio beneficio hipotético, imaginemos que estamos usando gcc test.c sin opciones estándar ni de advertencia.matrices de longitud cero frente a punteros

En particular estoy viendo los detalles debajo del capó. He agregado mi comprensión actual. ¿Estoy en lo cierto?

char **c1; //Size for a pointer is allocated on the stack. sizeof(c1) == sizeof(void*) 
char *c2[0]; //Nothing is allocated on the stack. sizeof(c2) == 0 

¿Hay alguna otra diferencia entre estos dos casos que no conozco (además de sizeof)?

struct a { 
    int i; 
    char c[0]; //sizeof(a) is sizeof(int)? a.c == (&i)+1? 
}; 

Según tengo entendido, esto se suele utilizar para las matrices de longitud variable al final de las estructuras. Pero ¿qué pasa con

struct b { 
    char *c[0] //sizeof(b) is 0? where does c point? 
}; 

int j; 
struct b myb; //myb.c == (&j)+1 == $esp? 

Además, ¿cómo está la dirección de una matriz de longitud cero si el espacio conocido por su puntero nunca se asigna a ninguna parte? Supongo que de la misma forma en que se conoce la dirección de un conjunto regular, pero estoy luchando por resolverlo en este momento.

+0

Ver también [aquí] (http://stackoverflow.com/a/14643530/912144). – Shahbaz

Respuesta

9

ISO C prohíbe 0 arrays de longitud.

char **c1; 

Esto define un objeto c1 de tipo char puntero a puntero a.

char *c2[0]; 

Esto es un error de compilación. No permitido. No en C, no en C++.

struct a { 
    int i; 
    char c[0]; //sizeof(a) is sizeof(int)? a.c == (&i)+1? 
}; 

Error como se indicó anteriormente: el tamaño de una matriz debe ser mayor que cero.

struct a { 
    int i; 
    char c[1]; 
}; 

tambien conocido como la estructura-Hack. Abusado de código de bajo nivel en casi todos los sistemas operativos: Linux, Windows.

C99 nos da una matriz sin apresto más conocido como miembro flexible-matriz:

struct a { 
    int i; 
    char c[]; /* note: no size */ 
}; 
+0

Ahh, pero si lo reescribió ias char c []; y tenía c como el último miembro de a, sería legal a partir de C99. Whee! – MSN

+0

@MSN - agregó que unos segundos antes de que se publicara su comentario :) – dirkgently

+0

Eso no siempre es un error en tiempo de compilación. gcc solo lo advierte, y eso es solo con -Wall y -pedantic flags. – mkb

12

La única vez que he visto matrices de longitud cero efectivamente utilizados cuando se desea tener una estructura de longitud variable .

como en este ejemplo tomado de here

struct line { 
     int length; 
     char contents[0]; 
    }; 

    struct line *thisline = (struct line *) 
     malloc (sizeof (struct line) + this_length); 
    thisline->length = this_length; 

Usted no desea utilizar un puntero en la estructura anterior como desea que los contenidos sean parte de la memoria asignada de la estructura.

Si hace un sizeof en la estructura anterior, no incluye ningún espacio para el contenido. No estoy seguro si esto alguna vez lo convirtió en un estándar, da advertencias en varios compiladores.

+0

Gracias por explicar el uso práctico de este modismo. Si es lo correcto es ir al grano si uno intenta comprender el código que hace uso de él. –

1

de la norma C99 (7.20.3), que trata de las funciones de asignación:

Cada uno de tales atribución se dió un puntero a un disjuntos objeto de cualquier otro objeto.

[...]

Si el tamaño del espacio solicitado es cero, el comportamiento es la aplicación definida: se devuelve ya sea un puntero nulo, o el comportamiento es como si el tamaño fueron algunos valor distinto de cero, excepto que el puntero devuelto no podrá ser utilizado para acceder a un objeto.

En otras palabras, en el caso de declarar b en la pila sin un inicializador (donde b disponga de c declarada como c[] en lugar de c[0]), el tamaño real de b en términos de espacio efectivamente utilizadas será> 0, ya que no puede acceder a ninguna parte de b. Si se asigna a través de malloc, se devolverá como 0 o como algún valor único al que no se puede acceder (si usa sizeof(b)).

+0

Seguramente esa sección de la norma solo aplica malloc? No puedo ver la relevancia de la primera parte de esta respuesta. ¿Qué significa que "el espacio realmente usado será> 0, ya que no puedes acceder a ninguna parte de b"? –

2

Puede obtener algunas respuestas aquí desde GCC docs. Pero eso se enfoca en el tema de tener una matriz de longitud cero como los últimos miembros de la estructura. No da respuestas directas con respecto a sizeof.

(como se ha puesto de manifiesto por otros, arrays de longitud cero no están en C estándar, pero eran en GNU C.)

0

Una matriz no puede tener tamaño cero.

ISO 9899:2011 6.7.6.2: 

If the expression is a constant expression, it shall have a value greater than zero. 

El texto anterior es verdadero tanto para una matriz simple (§1) como para una VLA (§5). Este es el texto normativo en el estándar C Un compilador no puede implementarlo de manera diferente.

gcc -std = c99 -pedantic le da una advertencia para esto.

Cuestiones relacionadas