¿Hay algún inconveniente en pasar estructuras por valor en C, en lugar de pasar un puntero?
Si la estructura es grande, obviamente existe el aspecto de rendimiento de copiar muchos datos, pero para una estructura más pequeña, básicamente debería ser lo mismo que pasar varios valores a una función.
Quizás sea aún más interesante cuando se usa como valores de retorno. C solo tiene valores de retorno únicos de las funciones, pero a menudo necesita varios. Entonces, una solución simple es ponerlos en una estructura y devolver eso.
¿Hay alguna razón a favor o en contra de esto?
Como podría no ser obvio para todos de lo que estoy hablando aquí, daré un ejemplo simple.
Si está programando en C, tarde o temprano comenzará a escribir funciones que se ven así:
void examine_data(const char *ptr, size_t len)
{
...
}
char *p = ...;
size_t l = ...;
examine_data(p, l);
Esto no es un problema El único problema es que tiene que estar de acuerdo con su compañero de trabajo en el orden en que deben estar los parámetros para que use la misma convención en todas las funciones.
Pero, ¿qué sucede cuando quieres devolver el mismo tipo de información? Por lo general, obtienes algo como esto:
char *get_data(size_t *len);
{
...
*len = ...datalen...;
return ...data...;
}
size_t len;
char *p = get_data(&len);
Esto funciona bien, pero es mucho más problemático. Un valor de retorno es un valor de retorno, excepto que en esta implementación no lo es. No hay forma de saber por lo anterior que la función get_data no puede ver a qué apunta len. Y no hay nada que haga que el compilador compruebe que un valor realmente se devuelve a través de ese puntero. Entonces, el próximo mes, cuando alguien más modifica el código sin entenderlo correctamente (¿porque no leyó la documentación?), Se rompe sin que nadie lo note, o comienza a fallar al azar.
Entonces, la solución que propongo es la estructura simple
struct blob { char *ptr; size_t len; }
Los ejemplos se pueden reescribir así:
void examine_data(const struct blob data)
{
... use data.tr and data.len ...
}
struct blob = { .ptr = ..., .len = ... };
examine_data(blob);
struct blob get_data(void);
{
...
return (struct blob){ .ptr = ...data..., .len = ...len... };
}
struct blob data = get_data();
Por alguna razón, creo que la mayoría de la gente instintivamente haría que exam_data tomara un puntero a un blob de estructura, pero no veo por qué. Todavía obtiene un puntero y un número entero, es mucho más claro que van juntos. Y en el caso de get_data, es imposible equivocarse de la manera que describí anteriormente, ya que no hay un valor de entrada para la longitud, y debe haber una longitud devuelta.
gettimeofday
) usan punteros en su lugar, y la gente lo toma como un ejemplo.
void examine data(const struct blob)
es incorrecto.