EDITAR: actualizó la sección "GRAN ERROR".
Una lección rápida sobre typedefs estilo C (diferente de C++!), Y por qué es cómo es y cómo usarlo.
En primer lugar, un truco tipo typedef básico.
typedef int* int_pointer;
int_pointer ip1;
int *ip2;
int a; // Just a variable
ip1 = &a; // Sets the pointer to a
ip2 = &a; // Sets the pointer to a
*ip1 = 4; // Sets a to 4
*ip2 = 4; // Sets a to 4
IP1 e IP2 son del mismo tipo: un tipo int-puntero a, a pesar de que usted no puso a * en la declaración de IP1. Eso * estaba en cambio en la declaración.
Cambiando de tema. Hablas de matrices se declaran como
int array1[4];
Para ello dinámicamente en tiempo de ejecución, es posible hacer:
int *array2 = malloc(sizeof(int) * 4);
int a = 4;
array1[0] = a;
array2[0] = a; // The [] implicitly dereferences the pointer
Ahora, lo que si queremos una matriz de punteros? Se vería así:
int *array1[4];
int a;
array1[0] = &a; // Sets array[0] to point to variable a
*array1[0] = 4; // Sets a to 4
Asignemos esa matriz dinámicamente.
int **array2 = malloc(sizeof(int *) * 4);
array2[0] = &a; // [] implicitly dereferences
*array2[0] = 4; // Sets a to 4
Observe la int **. Eso significa puntero-a puntero-a-int. Podemos, si elegimos, usar un puntero typedef.
typedef int* array_of_ints;
array_of_ints *array3 = malloc(sizeof(array_of_ints) * 4);
array3[0] = &a; // [] implicitly dereferences
*array3[0] = 4; // Sets a to 4
¿Ves que solo hay una * en esa última declaración? Eso es porque UNO de ellos está "en el typedef". Con esa última declaración, ahora tiene una matriz de tamaño 4 que consta de 4 punteros a ints (int *).
Es importante señalar PRECEDENCIA DEL OPERADOR aquí. El operador de desreferencia [] tiene preferencia sobre el * uno. Así que para ser absolutamente claro, lo que estamos haciendo es la siguiente:
*(array3[0]) = 4;
Ahora, vamos a cambiar los temas de Estructuras y typedefs.
struct foo { int a; }; // Declares a struct named foo
typedef struct { int a; } bar; // Typedefs an "ANONYMOUS STRUCTURE" referred to by 'bar'
¿Por qué alguna vez escribirías una estructura anónima? Bueno, para la legibilidad!
struct foo a; // Declares a variable a of type struct foo
bar b; // Notice how you don't have to put 'struct' first
Declarar una función ...
funca(struct foo* arg1, bar *arg2);
Vea como no teníamos que poner 'struct' delante de arg2?
Ahora, vemos que el código tiene que usar define una estructura de esta manera:
typedef struct { } * foo_pointers;
que es análogo a la forma en que hicimos una matriz de punteros antes:
typedef int* array_of_ints;
Comparar uno al lado del otro
typedef struct { } * foo_pointers;
typedef int* array_of_ints;
La única diferencia es que uno es para una struct {} y la otra es para int.
Con nuestros foo_pointers, se puede declarar una matriz de punteros a foo como tal:
foo_pointers fooptrs[4];
Ahora tenemos una matriz que almacena 4 punteros a una estructura anónima que no puede tener acceso.
TOPIC SWITCH!
DESAFORTUNADAMENTE PARA USTED, su maestro cometió un error. Si uno mira el tamaño de() del tipo foo_pointers arriba, encontrará que devuelve el tamaño de un puntero a esa estructura, NO el tamaño de la estructura. Esto es 4 bytes para la plataforma de 32 bits u 8 bytes para la plataforma de 64 bits. Esto se debe a que tipificamos un PUNTERO A UNA ESTRUCTURA, no una estructura en sí misma. sizeof (pStudentRecord) devolverá 4.
¡De modo que no puede asignar espacio para las estructuras de manera obvia! Sin embargo, los compiladores permiten esta estupidez. pStudentRecord no es un nombre/tipo que se puede usar para asignar memoria de forma válida, es un puntero a una estructura "conceptual" anónima, pero podemos suministrarle el tamaño de eso al compilador.
pStudnetRecord g_ppRegistros [2]; pStudentRecord * record = malloc (sizeof (* g_ppRecords [1]));
Un mejor práctica es hacer esto:
typedef struct { ... } StudentRecord; // Struct
typedef StudentRecord* pStudentRecord; // Pointer-to struct
Ahora tendríamos la capacidad de hacer estructura de StudentRecord, así como punteros a ellos con pStudentRecord de, de una manera clara.
Aunque el método que está obligado a utilizar es una práctica muy mala, no es exactamente un problema en este momento. Volvamos a nuestro ejemplo simplificado usando ints.
¿Qué pasa si quiero hacer un typedef para complicar mi vida, pero explicar el concepto que está pasando aquí? Volvamos al antiguo código int.
typedef int* array_of_ints;
int *array1[4];
int **array2 = malloc(sizeof(int *) * 4); // Equivalent-ish to the line above
array_of_ints *array3 = malloc(sizeof(array_of_ints) * 4);
int a, b, c, d;
*array1[0] = &a; *array1[1] = &b; *array1[2] = &c; *array1[3] = &d;
*array2[0] = &a; *array2[1] = &b; *array2[2] = &c; *array2[3] = &d;
*array3[0] = &a; *array3[1] = &b; *array3[2] = &c; *array3[3] = &d;
Como se puede ver, podemos usar esto con nuestra pStudentRecord:
pStudentRecord array1[4];
pStudentRecord *array2 = malloc(sizeof(pStudentRecord) * 4);
poner todo junto, y se sigue lógicamente que:
array1[0]->firstName = "Christopher";
*array2[0]->firstName = "Christopher";
son equivalentes. (Nota: no haga exactamente lo mismo que hice anteriormente, asignar un puntero char * en el tiempo de ejecución a una cadena solo es correcto si sabe que ya tiene suficiente espacio asignado).
Esto solo trae un último bit.¿Qué hacemos con todo este recuerdo que malloc'd? ¿Cómo lo liberamos?
free(array1);
free(array2);
Y hay un final de una lección tarde-noche en punteros, typedefs de estructuras anónimas, y otras cosas.
Un puntero solo apunta a una dirección. Puede tener reservada la mayor cantidad de memoria comenzando en esa dirección como desee (hasta que se quede sin espacio). – chris
Creo que es una pregunta pobre, entiendes que una matriz podría definirse de esa manera, ya que tratas de asignarle un espacio, entonces, ¿qué estás preguntando ?, no es suficiente asignar un espacio para el puntero a struct, que es btw pStudentRecord y no pSt ... ord *, para usarlo, ¡también necesita asignar un lugar para la estructura! – Michael