Existe-il des inconvénients à passer par les structures de la valeur C, plutôt que de passer un pointeur?
Si la structure est grande, il est évidemment le performancd aspect de la copie de beaucoup de données, mais pour une petite structure, il devrait être le même que le passage de plusieurs valeurs pour une fonction.
C'est peut-être encore plus intéressant lorsqu'il est utilisé comme valeur de retour. C ne dispose que seules les valeurs de retour des fonctions, mais vous avez souvent besoin de plusieurs années. Ainsi, une solution simple est de les mettre dans une struct et de retour que.
Existe-il des raisons pour ou contre?
Car elle pourrait ne pas être évident pour tout le monde ce dont je parle ici, je vais donner un exemple simple.
Si vous êtes à la programmation en C, vous aurez tôt ou tard commencer à écrire des fonctions qui ressemblent à ceci:
void examine_data(const char *ptr, size_t len)
{
...
}
char *p = ...;
size_t l = ...;
examine_data(p, l);
Ce n'est pas un problème. Le seul problème est que vous devez être d'accord avec votre collègue de travail, dans lequel la commande, les paramètres doivent être de sorte que vous utiliser la même convention, dans toutes les fonctions.
Mais qu'advient-il lorsque vous voulez retourner le même genre d'information? Généralement, vous obtenez quelque chose comme ceci:
char *get_data(size_t *len);
{
...
*len = ...datalen...;
return ...data...;
}
size_t len;
char *p = get_data(&len);
Cela fonctionne bien, mais est beaucoup plus problématique. Une valeur de retour est une valeur de retour, sauf que dans cette mise en œuvre, il n'est pas. Il n'y a aucun moyen de dire à partir de ce qui précède que la fonction get_data n'est pas permis de regarder ce que len points. Et il n'y a rien qui fait que le compilateur de vérifier qu'une valeur est retournée par le pointeur. Donc, le mois prochain, quand quelqu'un modifie le code sans le comprendre correctement (parce qu'il n'a pas lu la documentation?) il est cassé sans que personne s'en aperçoive, ou il commence à s'écraser au hasard.
Donc, la solution que je propose est simple struct
struct blob { char *ptr; size_t len; }
Les exemples peuvent être réécrites comme ceci:
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();
Pour une raison quelconque, je pense que la plupart des gens instinctivement faire examine_data prendre un pointeur vers une struct blob, mais je ne vois pas pourquoi. Il obtient toujours un pointeur et un entier, il est juste beaucoup plus clair qu'ils vont de pair. Et dans le get_data cas, il est impossible de désordre dans la façon dont je l'ai décrit avant, car il n'existe pas de valeur d'entrée pour la longueur, et il doit y avoir un retour de la longueur.