Supongamos que declaré una estructura C para contener información de configuración, que tiene muchos campos (~ 30), por ejemplo:
struct config { int a; int b; int c; ... char *str1; char *str2; ... };¿Cuál es la mejor manera de comparar dos estructuras sin simplemente enumerar y comparar cada elemento? Por supuesto, podría usar el siguiente código, pero mi pregunta es, ¿hay una manera más fácil de lograrlo?
static int cmpInstances(struct config *l, struct config *r) { return ( l->a == r->a && l->b == r->b && l->c == r->c && !strcmp(l->str1, r->str1) && !strcmp(l->str2, r->str2) ); } ¿Hay alguna macro que pueda hacer eso? Por ejemplo: cmpInstancesViaMacro(a,b,c) se expandiría a
l->a == r->a && l->b == r->b && l->c == r->cSe podría utilizar una variante generalizada de las denominadas macros X.
En el ejemplo de la pregunta, se vería así:
#define CONFIG_FIELDS \ X_INT(a) \ X_INT(b) \ X_INT(c) \ X_STRING(str1) \ X_STRING(str2) struct config { #define X_INT(NAME) int NAME; #define X_STRING(NAME) char *NAME; CONFIG_FIELDS #undef X_INT #undef X_STRING }; static int cmpInstances(struct config *l, struct config *r) { #define X_INT(NAME) l->NAME == r->NAME && #define X_STRING(NAME) strcmp(l->NAME, r->NAME) == 0 && return CONFIG_FIELDS 1; #undef X_INT #undef X_STRING } Con esta solución, solo se debe cambiar la macro CONFIG_FIELDS cuando se cambia la estructura, siempre que no haya cambios en el conjunto de tipos utilizados. La estructura y la función se mantendrían automáticamente sincronizadas.
Si se introduce un nuevo tipo, las macros X correspondientes deben definirse de manera similar a X_INT y X_STRING anteriores.
Quizás algunas macros nos ayuden a reducir las líneas de código y el esfuerzo necesario:
#define CMP(name) l->name == r->name && #define SCMP(name) !strcmp(l->name, r->name) && struct config { int a; int b; int c; char *str1; char *str2; }; static int cmpInstances(struct config *l, struct config *r) { return CMP(a) CMP(b) CMP(c) SCMP(str1) SCMP(str2) 1; } #undef CMP #undef SCMP Aquí definimos algunas macros que toman solo el nombre de la variable y las comparan. Uno está escrito para la comparación de enteros ( CMP ) y el otro está escrito para la comparación de cadenas ( SCMP ). Luego puede usar estas macros para comparar sus datos y undef cuando haya terminado.
Gracias a chqrlie por agregar 1 parte.
¿Cuál es la mejor manera de comparar dos estructuras sin simplemente enumerar y comparar cada elemento?
La forma presentada es la mejor. Excepto que los punteros deben apuntar a const : no se modifica nada.
¿Hay una manera más fácil de lograr esto?
La forma presentada es la forma más fácil de lograrlo, también es la más legible y autoexplicativa, fácil de refactorizar y razonar. Cualquier otro agregará complejidad y resultará en una carga de mantenimiento.
Encuentro strcmp(...) == 0 más claro que !strcmp(...) .