Variables globales et renvoyer plusieurs tableaux de longueurs variables (pointeurs) dans la fonction C

J’ai un peu d’expérience en programmation mais pas beaucoup avec C.

J’ai un fichier C assez volumineux. De nombreuses fonctions sont exécutées de manière séquentielle. Ainsi, dans ce cas particulier, aucune fonction n’est appelée deux fois, elles sont décomposées pour en faciliter la lecture, car chaque fonction a toujours un objective distinct.

Ce programme effectue beaucoup de calculs sur plusieurs tableaux longs de doubles à longueurs variables, ils sont donc tous des pointeurs. Deux questions:

1) Les variables qui sont calculées une fois depuis le début, puis servent à la saisie de nombreuses fonctions ultérieures. Devrais-je les transformer en variables globales dans ce fichier? D’après mon expérience de programmation dans des langages de niveau supérieur, les variables globales ne sont pas bonnes. N’est-ce pas le cas pour C et pourquoi?

2) Quand 1 de ma fonction veut renvoyer plusieurs pointeurs (chacun pointe sur un double tableau de longueur n par exemple), disons double * p1, double * p2, double * p3 qui sont liés, je peux les combiner dans une structure:

struct pointers { double *p1, *p2, *p3; } ptr; 

foo1 prendra en entrée double * et calcule ptr-> p1, ptr-> p2, ptr-> p3, puis ptr servira ultérieurement d’entrée pour foo2. Dois-je écrire

 struct pointers *foo(double *input) 

ou

 void foo1(double *input, struct pointers ptr) 

ou

 void foo1(double *input, struct pointers *ptr) 

Pourquoi les fonctions C sont-elles généralement des fonctions «vides», à moins qu’elles ne renvoient uniquement des variables int ou doubles? Avoir entrée et sortie à la fois comme parameters – est-ce déroutant?

Devrais-je initialiser ptr-> p1, ptr-> p2, ptr-> p3 à l’intérieur ou à l’extérieur de foo1?

Notez que foo () est la fonction principale qui appellera séquentiellement foo1, foo2.

Répondre à une question

1) Cela dépend vraiment de la size et de la scope de vos données. Si vous avez une petite quantité à utiliser dans le cadre du calcul au sein de votre fonction, il est plus logique de l’initialiser dans la fonction, limitant ainsi sa scope à la fonction.

Si la taille des données est de quelques mégaoctets, voire de plusieurs dizaines de kilo-octets, il est judicieux d’allouer un tas à l’aide d’un malloc.

Vous pouvez avoir des variables globales dans le fichier, mais vous devez ensuite vous préoccuper de la synchronisation de l’access à celles-ci – qui les modifie et dans quel ordre –

Pour répondre à la question 2) le meilleur moyen d’écrire une signature de fonction serait

 struct { double output1; double output2; double output3; } output_t; 

et la signature de fonction comme:

 ReturnCode foo ( double input , struct output_t * output); 

Où ReturnCode pourrait être juste et une valeur int indiquant si l’opération a réussi ou échoué.

1- Les variables globales sont fortement découragées dans C également. Ce sont deux raisons importantes:

  • La plupart du temps, il n’est pas nécessaire de disposer de variables tout au long du programme. Vous n’avez donc pas besoin de rendre les variables globales.
  • Avec les variables locales, votre code sera plus facile à gérer et vous éviterez d’éventuels effets secondaires .

Mais dans votre cas, comme vous l’avez dit, ptr.p1, ptr.p2, ptr.p3 deviendront des entrées pour de nombreuses autres fonctions ultérieures. Peut-être est-il préférable de le rendre global. Dans ce cas, si vous définissez global (uniquement dans ce fichier), vous devriez essayer le modificateur statique. Ici vous pouvez lire sur statique (il peut avoir 2 significations différentes)

2.Je pense que votre deuxième question “Avoir une entrée et une sortie en tant que parameters – est-ce déroutant?” cela dépend en fait du développeur, le langage vous donne les deux options, mais cela dépend de vous pour que le code soit clair.

Les variables globales ne sont pas non plus conseillées en C. Ce que je peux comprendre de votre question est que foo1 fera la structure et foo2 le prendra comme entrée.

Donc, à mon avis, vous devriez faire en sorte que foo1 retourne la structure puis transmette la structure entière en tant que paramètre à foo2

spécialement en C, les variables globales sont fortement déconseillées, sauf si vous travaillez sur plusieurs fichiers, chacun devant stocker ses données. il est beaucoup plus facile de grouper des données dans des structures et de les transmettre à des fonctions, ce qui rend le tout plus clair à comprendre

Voici un exemple de code que j’ai écrit et qui traite du travail avec les structures. seules les déclarations des fonctions sont ici mais vous obtenez le sens

 struct elem { void *data; struct elem *next; }; struct binky { struct elem *root; int elem_size; }; void Initialize(struct binky * b, int elem_size); int add(struct binky * b, const void * data); void *get(const struct binky * b, const void * data); void freeMap(struct binky * b);