2010-04-26 12 views
7

Para el fragmento de código C++ a continuación:matrices estáticas definidas con tamaño no especificado, corchetes vacíos?

class Foo { 
    int a[]; // no error 
}; 

int a[];  // error: storage size of 'a' isn't known 

void bar() { 
    int a[]; // error: storage size of 'a' isn't known 
} 

por qué no es la variable miembro causando un error también? y ¿cuál es el significado de esta variable miembro?

Estoy usando gcc versión 3.4.5 (mingw-vista special) a través de CodeBlocks 8.02.

En Studio Express 2008 Visual - Microsoft (R) C/C++ compilador de optimización 15.00.30729.01 de 80x86, que tiene los siguientes mensajes:

class Foo { 
    int a[]; // warning C4200: nonstandard extension used : zero-sized array in struct/union - Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array 
}; 

int a[]; 

void bar() { 
    int a[]; // error C2133: 'a' : unknown size 
} 

Ahora, esto necesita un poco de explicación también.

+0

El título menciona "matrices estáticas". ¿Dónde están estas "matrices estáticas" en su pregunta? No veo una sola referencia a ninguna "matriz estática". – AnT

+0

Me refiero a arreglos asignados estáticamente. Por favor, siéntase libre de editar la pregunta si lo considera necesario. Gracias. –

Respuesta

6

C99 es compatible con algo llamado un miembro de matriz 'flexible' que puede ser el último miembro de una estructura. Cuando asigna dinámicamente dicha estructura, puede aumentar la cantidad solicitada desde malloc() para proporcionar memoria para la matriz.

Algunos compiladores agregan esto como una extensión a C90 y/o C++.

para que pueda tener un código como el siguiente:

struct foo_t { 
    int x; 
    char buf[]; 
}; 


void use_foo(size_t bufSize) 
{ 
    struct foo_t* p = malloc(sizeof(struct foo_t) + bufSize); 

    int i; 

    for (i = 0; i < bufSize; ++i) { 
     p->buf[i] = i; 
    } 
} 

no se puede definir una estructura con un miembro de matriz flexible de forma directa (como una variable global/local o estática) como el compilador no lo hará saber cuánta memoria asignarle.

Sinceramente no estoy seguro de cómo se tendría que utilizar fácilmente tal cosa con new operador de C++ 's - Creo que tendría que asignar la memoria para el objeto utilizando malloc() y el uso de colocación new. Tal vez se podría utilizar una sobrecarga específica clase/estructura de operator new ...

2
class Foo { 
    int a[]; // OK in C, invalid in C++. Does not work with inheritance. 
}; // Idea is that structure is "extended" indefinitely by an array. 
    // May work on your compiler as an extra feature. 

int a[];  // error in C and C++: storage size of 'a' isn't known 

void bar() { 
    int a[]; // error in C and C++: storage size of 'a' isn't known 
} 

extern int a[]; // OK: storage size may be declared later. 

int a[5]; // declaration of size before use. 

Un tipo de matriz con un tamaño no especificado está incompleto. 8.3.4/1:

Si se omite la expresión constante, el tipo del identificador de D es "derivada-declaratoria-lista-tipo matriz de límite desconocido de T", un tipo de objeto incompleto.

Debe ser completada con el fin de participar en una definición, es decir, la definición de a debe contener una especificación de tamaño o de inicialización con una matriz de tamaño especificado.

+1

No entiendo el comentario "debe completarse antes de usar". Es perfectamente legal * usar * una matriz de tamaño no especificado en C++. No puede aplicar 'sizeof' a él, pero puede acceder legalmente a sus elementos. – AnT

+0

@Andrey: un argumento de función declarado como una matriz de tamaño no especificado tiene el tipo 'T *'. Es un decaimiento a otro tipo. ¿Hay algún otro ejemplo que deba tener en cuenta? Tu respuesta no parece mostrar ninguna. – Potatoswatter

+0

No estaba hablando de argumentos de función, que es una historia completamente diferente. Estaba refiriéndome a la declaración 'extern int a []' en su ejemplo. Una vez que declaras una matriz como esa, puedes * usar * ya. Veo que eliminaste la referencia a "usar". – AnT

0

Hemos utilizado esto para denotar un registro de longitud variable de algún tipo. Algo así como un archivo de encabezado que tiene información sobre la cantidad de estructuras a seguir, seguido de los datos en sí. Es una matriz de longitud variable y he encontrado que no es compatible bien entre compiladores. Algunos quieren matriz []; y algunos quieren matriz [0]; (viejo estilo).

idioma
11

C++ permite la omisión de tamaño de la matriz sólo en declaraciones no definen

extern int a[]; // non-defining declaration - OK in C++ 

int a[]; // definition - ERROR in C++ 

int a[5]; // definition - OK, size specified explicitly 
int a[] = { 1, 2, 3 }; // definition - OK, size specified implicitly 

decarations miembro de clase no estáticos son siempre necesarios para especificar el tamaño de la matriz

struct S { 
    int a[]; // ERROR in C++ 
}; 

mientras miembro de la clase estática decarations puede omitir el tamaño

struct S { 
    static int a[]; // OK in C++ 
}; 

(la definición del mismo miembro, por supuesto, tendrá que especificar el tamaño).

Cualquier desviación de este comportamiento solo puede explicarse por el comportamiento extendido no estándar de su compilador. Tal vez debería especificar algunas configuraciones de compilación adicionales para que se comporte de una manera más pedante.

Cuestiones relacionadas