59 votes

Pourquoi utiliser l'adresse du premier élément de la structure, plutôt que la structure elle-même ?

Je viens de découvrir une autre base de code au travail où les développeurs utilisent systématiquement l'adresse du premier élément des structures lors de la copie/comparaison/réglage, plutôt que la structure elle-même. Voici un exemple simple.

Il y a d'abord un type de structure :

typedef struct {
    int a;
    int b;
} foo_t;

Ensuite, il y a une fonction qui fait une copie d'une telle structure :

void bar(foo_t *inp)
{
    foo_t l;
    ...
    memcpy(&l.a, &inp->a, sizeof(foo_t));
    ...
}

Je n'écrirais pas moi-même un appel à memcpy de cette façon et j'ai commencé à soupçonner que les développeurs originaux n'avaient tout simplement pas bien compris les pointeurs et les structures en C. Cependant, maintenant, j'ai vu cela dans deux bases de code sans rapport, sans développeurs communs, donc je commence à douter de moi-même.

Pourquoi vouloir utiliser ce style ?

62voto

Artur Points 3152

Personne ne devrait faire cela. Si vous réorganisez les membres de la structure, vous aurez des problèmes.

62voto

ouah Points 75311

Au lieu de ça :

memcpy(&l.a, &inp->a, sizeof(foo_t));

vous pouvez le faire :

memcpy(&l, inp, sizeof(foo_t));

Bien que cela puisse être dangereux et trompeur, les deux déclarations font en fait la même chose ici, car C garantit qu'il n'y a pas de remplissage avant le premier membre de la structure.

Mais le mieux est de copier les objets de la structure en utilisant un simple opérateur d'affectation :

l = *inp;

Pourquoi vouloir utiliser ce style ?

Mon avis : ignorance ou mauvaise discipline.

16voto

plinth Points 26817

On ne le ferait pas. Si vous avez déjà déménagé a dans la structure ou que vous insériez un ou plusieurs membres avant elle, vous introduiriez un bug de destruction de la mémoire.

12voto

Darren Stone Points 1052

Ce code n'est pas sûr car le réarrangement des membres de la structure peut entraîner l'apparition de la fonction memcpy accéder au-delà des limites de la structure si le membre a n'est plus le premier membre.

Cependant, il est concevable que les membres soient intentionnellement ordonnés dans la structure et que le programmeur ne veuille copier qu'un sous-ensemble d'entre eux, débutant avec membre a et fonctionne jusqu'à la fin de la structure. Si c'est le cas, le code peut être sécurisé avec la modification suivante :

    memcpy(&l.a, &inp->a, sizeof(foo_t) - offsetof(foo_t, a));

Maintenant les membres de la structure peuvent être réarrangés dans n'importe quel ordre et ceci memcpy ne sortira jamais des limites du terrain.

1voto

Chris Fox Points 115

C'est une très mauvaise habitude. La structure peut avoir un autre membre en préambule, par exemple. C'est une habitude follement imprudente et je suis surpris de lire que quelqu'un puisse faire cela.

D'autres l'ont déjà noté ; celui qui me dérange est le suivant :

struct Foo rgFoo [3];
struct Foo *pfoo = &rgFoo [0];

au lieu de

struct Foo *pfoo = rgfoo;

Pourquoi déréférencer le tableau par index et ensuite reprendre l'adresse ? C'est déjà l'adresse, la seule différence notable est que pfoo est techniquement

struct Foo *const, 

pas

struct Foo *.  

Pourtant, je voyais le premier tout le temps.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X