punteros - matriz dinamica c++
¿Cómo incluir una matriz dinámica DENTRO de una estructura en C? (8)
He mirado alrededor pero no he podido encontrar una solución a lo que debe ser una pregunta bien hecha. Aquí está el código que tengo:
#include <stdlib.h>
struct my_struct {
int n;
char s[]
};
int main()
{
struct my_struct ms;
ms.s = malloc(sizeof(char*)*50);
}
y aquí está el error que gcc me da: error: uso no válido del miembro flexible de la matriz
Puedo hacer que compile si declaro que la declaración de s dentro de la estructura es
char* s
y esta es probablemente una implementación superior (la aritmética del puntero es más rápida que las matrices, ¿no?) pero pensé en una declaración de ca
char s[]
es lo mismo que
char* s
la aritmética del puntero es más rápida que las matrices, ¿sí?
Para nada, en realidad son lo mismo. las matrices se traducen en aritmética de punteros en tiempo de compilación.
char test[100];
test[40] = 12;
// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;
Debes decidir qué es lo que estás tratando de hacer primero.
Si desea tener una estructura con un puntero a una matriz [independiente] dentro, debe declararla como
struct my_struct {
int n;
char *s;
};
En este caso, puede crear el objeto struct real de la manera que desee (como una variable automática, por ejemplo)
struct my_struct ms;
y luego asignar la memoria para la matriz de forma independiente
ms.s = malloc(50 * sizeof *ms.s);
De hecho, no hay una necesidad general de asignar dinámicamente la memoria de matriz.
struct my_struct ms;
char s[50];
ms.s = s;
Todo depende del tipo de vida que necesites de estos objetos. Si su estructura es automática, entonces en la mayoría de los casos la matriz también sería automática. Si el objeto struct posee la memoria de la matriz, simplemente no tiene sentido hacer lo contrario. Si la estructura en sí es dinámica, entonces la matriz también debería ser normalmente dinámica.
Tenga en cuenta que en este caso tiene dos bloques de memoria independientes: la estructura y la matriz.
Un enfoque completamente diferente sería usar el modismo "struct hack". En este caso, la matriz se convierte en una parte integral de la estructura. Ambos residen en un solo bloque de memoria. En C99, la estructura se declararía como
struct my_struct {
int n;
char s[];
};
y para crear un objeto, tendrías que asignarlo todo dinámicamente
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
El tamaño del bloque de memoria en este caso se calcula para acomodar los miembros de la estructura y la matriz final del tamaño del tiempo de ejecución.
Tenga en cuenta que en este caso no tiene la opción de crear tales objetos de estructura como objetos estáticos o automáticos. Las estructuras con miembros de matriz flexible al final solo se pueden asignar dinámicamente en C.
Su suposición acerca de que las aritméticas del puntero son más rápidas que las matrices es absolutamente incorrecta. Las matrices funcionan a través de aritmética de puntero por definición, por lo que son básicamente las mismas. Además, una matriz genuina (no decaída a un puntero) generalmente es un poco más rápida que un objeto puntero. El valor del puntero debe leerse desde la memoria, mientras que la ubicación de la matriz en la memoria es "conocida" (o "calculada") desde el propio objeto de la matriz.
El uso de una matriz de tamaño no especificado solo se permite al final de una estructura, y solo funciona en algunos compiladores. Es una extensión de compilador no estándar. (Aunque creo que recuerdo que C ++ 0x permitirá esto).
Sin embargo, la matriz no será una asignación separada para la estructura. Por lo tanto, debe asignar todos my_struct
, no solo la parte de la matriz.
Lo que hago es simplemente darle a la matriz un tamaño pequeño pero diferente de cero. Normalmente 4 para matrices de caracteres y 2 para matrices wchar_t
para preservar la alineación de 32 bits.
Luego puede tomar en cuenta el tamaño declarado de la matriz cuando realiza la asignación. A menudo no lo hago con la teoría de que el slop es más pequeño que la granularidad en la que trabaja el heap manager en cualquier caso.
Además, creo que no debería usar sizeof (char *) en su asignación.
Esto es lo que haría.
struct my_struct {
int nAllocated;
char s[4]; // waste 32 bits to guarantee alignment and room for a null-terminator
};
int main()
{
struct my_struct * pms;
int cb = sizeof(*pms) + sizeof(pms->s[0])*50;
pms = (struct my_struct*) malloc(cb);
pms->nAllocated = (cb - sizoef(*pms) + sizeof(pms->s)) / sizeof(pms->s[0]);
}
Hay muchas respuestas con respecto a la matriz flexible C99.
Quería comentar la respuesta de Alexander Gessler respecto a que los punteros son lo mismo que las matrices.
Ellos no son; Arrays es una expresión, los punteros son una variable.
SÍ TIENEN diferencias sutiles, especialmente al atravesar GRANDES cantidades de datos. A veces es necesario exprimir cada mSec (trabajo en sistemas gráficos integrados).
La forma en que lo tiene escrito ahora, solía llamarse "struct hack", hasta que C99 lo bendijo como un "miembro de matriz flexible". El motivo por el que recibe un error (probablemente de todos modos) es que debe ir seguido de un punto y coma:
#include <stdlib.h>
struct my_struct {
int n;
char s[];
};
Cuando asigna espacio para esto, desea asignar el tamaño de la estructura más la cantidad de espacio que desea para la matriz:
struct my_struct *s = malloc(sizeof(struct my_struct) + 50);
En este caso, el miembro de matriz flexible es una matriz de char, y sizeof (char) == 1, por lo que no es necesario multiplicar por su tamaño, pero al igual que cualquier otro malloc que necesitaría si fuera un matriz de algún otro tipo:
struct dyn_array {
int size;
int data[];
};
struct dyn_array* my_array = malloc(sizeof(struct dyn_array) + 100 * sizeof(int));
Editar: Esto da un resultado diferente al cambiar el miembro a un puntero. En ese caso, usted (normalmente) necesita dos asignaciones separadas, una para la propia estructura y otra para los datos "adicionales" a los que apunta el puntero. Usando un miembro de matriz flexible puede asignar todos los datos en un solo bloque.
Las matrices se resolverán con punteros, y aquí debe definir s
como char *s
. La estructura es básicamente un contenedor, y el must (IIRC) debe tener un tamaño fijo, por lo que no es posible tener una matriz de tamaño dinámico dentro de él. Como de todos modos está malloc
la memoria, esto no debería hacer ninguna diferencia en lo que está buscando.
Básicamente, dices que s
indicará una ubicación de memoria. Tenga en cuenta que todavía puede acceder a esto más adelante usando notación como s[0]
.
Sospecho que el compilador no sabe cuánto espacio necesitará asignar para s [], si decide declarar una variable automática con él.
Estoy de acuerdo con lo que dijo Ben, declara tu estructura
struct my_struct {
int n;
char s[1];
};
Además, para aclarar su comentario sobre el almacenamiento, declarar char *s
no pondrá la estructura en la pila (ya que está dinámicamente asignada) y asignará s
en el montón, lo que hará es interpretar el primer sizeof(char *)
bytes sizeof(char *)
de su matriz como un puntero, por lo que no estará operando con los datos que cree que es, y probablemente será fatal.
Es vital recordar que aunque las operaciones en punteros y arreglos se pueden implementar de la misma manera, no son la misma cosa.
el código generado será idéntico (matriz y ptr). Aparte del hecho de que la matriz no compilará
y por cierto, hazlo c ++ y usa el vector