Termino el tema un poco rapido por falta de tiempo..
Al definir
Le estoy diciendo que "Micuenta" tiene el formato de la estructura "account", es en ese momento que realmente estoy definiendo mi variable ( la que ocupa espacio de memoria), antes solo defini como estaria formado ( el formato, la definicion, como quieras llamarle) pero que si esta y yo no creo ninguna variable eso no va a ocupar espacio en memoria. Algunas veces muchos declaran la variable en el mismo lugar donde definen la estructura.
struct account {
int account_number;
char *first_name;
char *last_name;
float balance;
} Micuenta, SegundaCuenta;
Es totalmente valido. Y es lo unico que me quedaba de estructuras, estan los bit fields pero que puede llevar a errores de portabilidad por que no siempre se respeta el orden, ya que el standard de C no dice nada y queda libre a el compilador.
Por que usar typedef ?typedef es para crear un tipo de variable (una traduccion seria "definir un nuevo tipo"). Asi como tenemos int, char, bool, podemos crear una variable.
El formato es :
typedef origen destino;
Y tranquilamente podria hacer:
Por lo cual MiVariable es del tipo "MiEntero", ( aunque en este caso sea lo mismo que poner int, pero hay mas complicadas)
Ahora veamos un caso con estructuras, donde tenemos funciones que devuelven estructuras, pasan argumentos con estructuras, etc.
struct MyStruct {
elemento 1;
elemento 2;
};
struct MyStruct FuncionNumero1(int valor, struct MyStruct EstructuraRecibida)
{
struct MyStruct NuevaEstructura;
.....;
}
Como que tenemos que escribir siempre struct MyStruct, ahora si definimos un tipo nuevo. Digamos que le damos el nombre "MyStruct_t" ( la t de tipo ) se vuelve mas facil trabajar con estas
struct MyStruct {
elemento 1;
elemento 2;
};
typedef struct MyStruct MyStruct_t;
MyStruct_t FuncionNumero1(int valor, MyStruct_t EstructuraRecibida)
{
MyStruct_t NuevaEstructura;
.....;
}
Pero este no es el unico caso, como decia en el ultimo ejemplo de mi anterior post se uso, pero no con ese motivo. Sino otro.
typedef struct list_element list_element;
struct list_element {
int p;
list_element * next;
};
Lo primero a observar es que el tag_name ( o identificador de la estructura: list_element ) puede usarse el mismo texto como un tipo, y no produciria ningun error, por eso los nombres son iguales en el typedef de este ejemplo. es decir typedef struct list_element list_element; estoy diciendo que cree un nuevo tipo llamado list_element ( el ultimo ) y que sea igual a "struct list_element" ( struct + tag_name de la estructura )
Segundo, Si hacemos una estructura, que adentro debe poseer la misma estructura tendriamos un error, me refiero a estar parte unica del codigo sin el typedef:
struct list_element {
int p;
list_element * next;
};
, por que en ese momento todavia no esta la definicion completa de la estructura (y no existe list_element per se ), existen 2 formas de hacerlo si no mal recuerdo ( que hace mucho que no lo uso). La primera es declarar la estructura primero, asi "existe" por mas que no le digamos que tiene dentro o como esta formada.
struct list_element;
struct list_element {
int p;
struct list_element * next;
};
La segunda es definir un tipo, que es el caso del codigo de ejemplo, se observa que tanto el struct list_element, como la creacion del tipo por el typedef no generar error a pesar de estar sus definiciones "vacias".
Hay mas cosas sobre las estructuras. Como por ejemplo uno asume muchas veces que los datos estan todos seguidos, y vas a ver gente creando codigo en el cual acceden a las estructuras con punteros a 8bits por ejemplo. Esto no trae ningun problema en un micro de 8 bits. El problema pasa cuando te vas a otro de 16bits. C te asegura que el orden de los elementos sea igual que los escribiste, PERO, no te asegura que van a estar contiguos, sino que los va a acomodar como a el le guste, y por ejemplo en un micro de 8 bits que te podia ocupar 40bytes tu estructura, en un micro de 16 bits tal ves ocupe 44 bytes, donde esos 4 que se agregan es lo que se llama padding. Es lo unico a remarcar creo.
Respecto a los typedef, una recomendacion es NO usar typedef con punteros!. Ya que ocultan al programar el mismo, es decir:
typedef *int MiPEntero;
MiPEntero Myptr;
Si uno lee, aunque aca esta muy claro, pero en un archivo medio grande la definicion de los typedef quedan escondidos o son pocos visibles, si alguien encuentra eso en el codigo, pensara que es un variable mas, pero que en realidad es un puntero, eso se intenta evitar de hacer, aunque el ejemplo no tiene sentido, se podria aplicar por ejemplo a un puntero de una estructura.