una que miembros flexibles bombas bomba aspas c++ flexible-array-member

que - ¿Los miembros flexibles de la matriz son válidos en C++?



bombas de miembros flexibles (6)

En C99, puede declarar un miembro de matriz flexible de una estructura como tal:

struct blah { int foo[]; };

Sin embargo, cuando alguien aquí en el trabajo intentó compilar algún código usando clang en C ++, esa sintaxis no funcionó. (Había estado trabajando con MSVC.) Tuvimos que convertirlo a:

struct blah { int foo[0]; };

Revisando el estándar de C ++, no encontré ninguna referencia a matrices de miembros flexibles; Siempre pensé que [0] era una declaración inválida, pero aparentemente para una matriz de miembros flexible es válida. ¿Las matrices de miembros flexibles son realmente válidas en C ++? Si es así, ¿es la declaración correcta [] o [0] ?


Both int foo[]; y int foo[0]; son incorrectos en C ++ (al menos en ese contexto). Use int *foo; .

Cuando declaras dicha matriz en C ++, su tamaño debe definirse en tiempo de compilación. Es decir, debería especificar el tamaño de la matriz explícitamente, como int foo[5] o usar la lista de inicialización como int foo[] = {1, 2, 3} . Desafortunadamente, no puede usar la lista de inicialización para la inicialización del miembro de la clase.

EDITAR

Para fines de serialización, use std::vector<int> foo . Una vez que se completa, puede obtener fácilmente un puntero a una matriz de enteros y su tamaño:

int* begin = &foo[0]; std::size_t size = foo.size();


C ++ no es compatible con los miembros de matriz flexible C99 al final de las estructuras, ya sea utilizando una notación de índice vacía o una notación de índice 0 (salvo las extensiones específicas del proveedor):

struct blah { int count; int foo[]; // not valid C++ }; struct blah { int count; int foo[0]; // also not valid C++ };

Por lo que yo sé, C ++ 0x tampoco agregará esto.

Sin embargo, si dimensiona la matriz en 1 elemento:

struct blah { int count; int foo[1]; };

las cosas son válidas y funcionan bastante bien. Puede asignar la memoria adecuada con una expresión que es poco probable que tenga errores uno a uno:

struct blah* p = (struct blah*) malloc( offsetof(struct blah, foo[desired_number_of_elements]); if (p) { p->count = desired_number_of_elements; // initialize your p->foo[] array however appropriate - it has `count` // elements (indexable from 0 to count-1) }

Por lo tanto, es portátil entre C90, C99 y C ++ y funciona tan bien como los miembros de matriz flexible de C99.

Raymond Chen hizo un buen comentario sobre esto: ¿por qué algunas estructuras terminan con una matriz de tamaño 1?

Nota: En el artículo de Raymond Chen, hay un error tipográfico / error en un ejemplo inicializando la matriz ''flexible''. Debe leer:

for (DWORD Index = 0; Index < NumberOfGroups; Index++) { // note: used ''<'' , not ''='' TokenGroups->Groups[Index] = ...; }


C ++ se estandarizó por primera vez en 1998, por lo que es anterior a la adición de miembros de matriz flexible a C (que era nuevo en C99). Hubo un corrigendum para C ++ en 2003, pero eso no agregó ninguna característica nueva relevante. La próxima revisión de C ++ (C ++ 0x) aún está en desarrollo, y parece que los miembros flexibles de la matriz no se agregan a ella.


El segundo no contendrá elementos, sino que señalará justo después de blah . Entonces, si tienes una estructura como esta:

struct something { int a, b; int c[0]; };

puedes hacer cosas como esta:

struct something *val = (struct something *)malloc(sizeof(struct something) + 5 * sizeof(int)); val->a = 1; val->b = 2; val->c[0] = 3;

En este caso, c se comportará como una matriz con 5 int s, pero los datos en la matriz serán posteriores a la estructura something .

El producto en el que estoy trabajando usa esto como una cadena de tamaño:

struct String { unsigned int allocated; unsigned int size; char data[0]; };

Debido a las arquitecturas compatibles, esto consumirá 8 bytes más allocated .

Por supuesto, todo esto es C pero g ++ por ejemplo lo acepta sin problemas.


La mejor solución es declararlo como un puntero:

struct blah { int* foo; };

O mejor aún, declararlo como un std::vector :

struct blah { std::vector<int> foo; };


Si solo quieres

struct blah { int foo[]; };

entonces no necesitas la estructura en absoluto y simplemente puedes tratar con una matriz int malloc''ed / new''ed.

Si tienes algunos miembros al principio:

struct blah { char a,b; /*int foo[]; //not valid in C++*/ };

luego en C ++, supongo que podrías reemplazar a foo con una función de miembro foo :

struct blah { alignas(int) char a,b; int *foo(void) { return reinterpret_cast<int*>(&this[1]); } };

Ejemplo de uso:

#include <stdlib.h> struct blah { alignas(int) char a,b; int *foo(void) { return reinterpret_cast<int*>(&this[1]); } }; int main() { blah *b = (blah*)malloc(sizeof(blah)+10*sizeof(int)); if(!b) return 1; b->foo()[1]=1; }