lenguaje - ¿Por qué usar la dirección del primer elemento de struct, en lugar de struct?
punteros en c (6)
En lugar de eso:
memcpy(&l.a, &inp->a, sizeof(foo_t));
usted puede hacer eso:
memcpy(&l, inp, sizeof(foo_t));
Si bien puede ser peligroso y engañoso, ambas afirmaciones en realidad hacen lo mismo aquí ya que C garantiza que no hay relleno antes del primer miembro de la estructura.
Pero lo mejor es copiar los objetos de estructura con un simple operador de asignación:
l = *inp;
¿Por qué querría uno usar este estilo?
Mi suposición: ignorancia o mala disciplina.
Acabo de encontrar otra base de código en el trabajo donde los desarrolladores utilizan consistentemente la dirección del primer elemento de estructuras al copiar / comparar / configurar, en lugar de la estructura en sí. Aquí hay un ejemplo simple.
Primero hay un tipo de estructura:
typedef struct {
int a;
int b;
} foo_t;
Luego hay una función que hace una copia de dicha estructura:
void bar(foo_t *inp)
{
foo_t l;
...
memcpy(&l.a, &inp->a, sizeof(foo_t));
...
}
No me gustaría escribir una llamada a memcpy
de esa manera y comencé sospechando que los desarrolladores originales simplemente no entendían los punteros y las estructuras en C. Sin embargo, ahora he visto esto en dos bases de código no relacionadas, con no hay desarrolladores comunes, así que estoy empezando a dudar de mí mismo.
¿Por qué querría uno usar este estilo?
En realidad, hay un caso de uso legítimo para esto: construir una jerarquía de clases.
Al tratar structs como instancias de clase, el primer miembro (es decir, el desplazamiento 0) será típicamente la instancia de supertipo ... si existe un supertipo. Esto permite que un elenco simple se mueva entre el subtipo y el supertipo. Muy útil.
En la nota de Darren Stone sobre la intención, esto se espera al ejecutar OO en el lenguaje C.
En cualquier otro caso , sugeriría evitar este patrón y acceder al miembro directamente en su lugar, por razones ya citadas.
Es un mal hábito. La estructura puede tener otro miembro antepuesto, por ejemplo. Este es un hábito insanamente descuidado y me sorprende leer que alguien haría esto.
Otros ya han notado esto; el que me molesta es esto:
struct Foo rgFoo [3];
struct Foo *pfoo = &rgFoo [0];
en lugar de
struct Foo *pfoo = rgfoo;
¿Por qué deref la matriz por índice y luego tomar la dirección de nuevo? Ya es la dirección, la única diferencia de la nota es que pfoo es técnicamente
struct Foo *const,
no
struct Foo *.
Sin embargo, solía ver el primero todo el tiempo.
Este código no es seguro porque reorganizar los miembros de la estructura puede hacer que memcpy
acceda más allá de los límites de la estructura si el miembro a
ya no es el primer miembro.
Sin embargo, es concebible que los miembros estén intencionalmente ordenados dentro de la estructura y el programador solo quiera copiar un subconjunto de ellos, comenzando con el miembro a
y ejecutándose hasta el final de la estructura. Si ese es el caso, entonces el código puede hacerse seguro con el siguiente cambio:
memcpy(&l.a, &inp->a, sizeof(foo_t) - offsetof(foo_t, a));
Ahora los miembros de la estructura pueden reorganizarse en cualquier orden y esta memcpy
nunca se saldrá de los límites.
Nadie debería hacer eso. Si reorganizas los miembros de la estructura, estás en problemas.
Uno no lo haría. Si alguna vez movió a
en la estructura o insertó miembro (s) antes, introduciría un error de memoria.