Pasar una estructura por referencia y manipularla
-
06-07-2019 - |
Pregunta
typedef struct unit_class_struct {
char *name;
char *last_name;
} person;
int setName(person *array) {
array[0].name = strdup("Bob");
array[1].name = strdup("Dick");
return 1;
}
int setLastName(person *array) {
array->last_name = strdup("Sanchez");
array++;
array->last_name = strdup("Clark");
return 1;
}
int main()
{
person array[10];
person *pointer;
pointer = array;
setName(pointer);
setLastName(pointer);
printf("First name is %s %s\n", array[0].name, array[0].last_name);
printf("Second name is %s %s\n", array[1].name, array[1].last_name);
while(1) {}
return 0;
}
Este es un código de ejemplo que se me ocurrió para jugar con las estructuras. Observe la forma en que configuré el nombre en setName y la forma en que lo hice en setLastName.
Ambos funcionan, pero tengo curiosidad ¿cuál es la diferencia entre las dos formas en que lo hice?
¿Es una forma mejor que la otra?
¿También es necesario strdup en este ejemplo? Si no, ¿sería necesario si estuviera configurando array.name en variables de tamaño aleatorio en lugar de literales de cadena?
Solución
Usar el enfoque indexado es un poco más claro que usar la aritmética del puntero, en mi opinión, pero tampoco funciona. Sospecho que el código que genera el compilador para cada uno es bastante similar en ambos casos.
strdup
es necesario en este caso si está trabajando con variables porque no asigna memoria para guardar sus valores de cadena en la estructura person
. Si ya había asignado espacio para esas cadenas cuando se llamó a cualquiera de sus setters, strcpy
( strcpy_s
, preferiblemente) sería suficiente.
Cuando trabaje con literales como en su ejemplo, strdup
no es necesario: puede asignar directamente al char *
.
Otros consejos
Si establece todos sus .name en constantes de cadena, entonces no, strdup
no es estrictamente necesario. Lo querrá si va a modificar la cadena más tarde. Una mejor base en la gestión de punteros y memoria aclarará la distinción. Si utiliza strdup
, asegúrese de liberar
el resultado más tarde.
Ambas opciones son bastante arriesgadas, porque no conoce la longitud de la matriz. En consecuencia, acceder al resultado de array ++ o array [1] podría generar un comportamiento indefinido.
Quizás podrías probar esta aplicación
int set_last_name(person* array, char* lastnames[],size_t amount){
int i=0;
for(;i<amount;i++,array++){
strncpy(array->lastname,lastnames[i],strlen(lastnames[i]));
}
return 1;
}
donde cantidad es la longitud de la matriz de apellidos.
Tenga en cuenta que no hay uso de strdup. Esta función esperaría que el usuario asigne memoria para apellidos y matriz. Entonces el usuario debe liberar esa memoria, si es necesario. No me gusta strdup porque devuelve una cadena asignada en el montón, y en el caso de sus funciones, debe documentarse claramente que el usuario de las funciones tiene que liberarla.
array- > name
es exactamente lo mismo que (* array) .name
.
En ambas funciones " array " es un puntero a una estructura, por lo que tanto * array
como array [0]
son estructuras y puede establecer sus miembros. La notación de flecha es solo un atajo de uso frecuente.