Comment puis-je retourner plusieurs valeurs d’une fonction dans C?

Si j’ai une fonction qui produit un résultat int et une ssortingng résultat, comment puis-je les retourner d’une fonction?

Autant que je sache, je ne peux retourner qu’une seule chose, comme déterminé par le type précédant le nom de la fonction.

Je ne sais pas quelle est votre ssortingng , mais je vais supposer qu’elle gère sa propre mémoire.

Vous avez deux solutions:

1: Renvoyer une struct contenant tous les types dont vous avez besoin.

 struct Tuple { int a; ssortingng b; }; struct Tuple getPair() { Tuple r = { 1, getSsortingng() }; return r; } void foo() { struct Tuple t = getPair(); } 

2: Utilisez des pointeurs pour dissortingbuer des valeurs.

 void getPair(int* a, ssortingng* b) { // Check that these are not pointing to NULL assert(a); assert(b); *a = 1; *b = getSsortingng(); } void foo() { int a, b; getPair(&a, &b); } 

La méthode que vous choisissez d’utiliser dépend en grande partie de vos préférences personnelles quant à la sémantique que vous préférez.

Option 1 : Déclarez une structure avec un int et une chaîne et retournez une variable struct.

 struct foo { int bar1; char bar2[MAX]; }; struct foo fun() { struct foo fooObj; ... return fooObj; } 

Option 2 : Vous pouvez passer l’un des deux via le pointeur et apporter des modifications au paramètre réel via le pointeur et retourner l’autre comme d’habitude:

 int fun(char **param) { int bar; ... strcpy(*param,"...."); return bar; } 

ou

  char* fun(int *param) { char *str = /* malloc suitably.*/ ... strcpy(str,"...."); *param = /* some value */ return str; } 

Option 3 : similaire à l’option 2. Vous pouvez passer les deux via le pointeur et ne rien retourner de la fonction:

 void fun(char **param1,int *param2) { strcpy(*param1,"...."); *param2 = /* some calculated value */ } 

Deux approches différentes:

  1. Transmettez vos valeurs de retour par pointeur et modifiez-les dans la fonction. Vous déclarez votre fonction comme nulle, mais elle retourne via les valeurs transmises sous forme de pointeurs.
  2. Définissez une structure qui regroupe vos valeurs de retour.

Je pense que le n ° 1 est un peu plus clair sur ce qui se passe, même si cela peut devenir fastidieux si vous avez trop de valeurs de retour. Dans ce cas, l’option n ° 2 fonctionne assez bien, bien que la création de structures spécialisées à cette fin entraîne des coûts indirects.

Comme l’un de vos types de résultat est une chaîne (et que vous utilisez C, pas C ++), je vous recommande de passer des pointeurs en tant que parameters de sortie. Utilisation:

 void foo(int *a, char *s, int size); 

et appelez comme ceci:

 int a; char *s = (char *)malloc(100); /* I never know how much to allocate :) */ foo(&a, s, 100); 

En général, préférez faire l’allocation dans la fonction appelante , pas à l’intérieur de la fonction elle-même, afin que vous puissiez être aussi ouvert que possible pour différentes stratégies d’allocation.

Créez une structure et définissez deux valeurs à l’intérieur et retournez la variable struct.

 struct result { int a; char *ssortingng; } 

Vous devez allouer de l’espace pour le caractère char * dans votre programme.

Utilisez les pointeurs comme parameters de fonction. Ensuite, utilisez-les pour renvoyer plusieurs valeurs.

En passant des parameters par référence à la fonction.

Exemples:

  void incInt(int *y) { (*y)++; // Increase the value of 'x', in main, by one. } 

Aussi en utilisant des variables globales mais ce n’est pas recommandé.

Exemple:

 int a=0; void main(void) { //Anything you want to code. } 

Une approche consiste à utiliser des macros. Placez ceci dans un fichier d’en-tête multitype.h

 #include  /* ============================= HELPER MACROS ============================= */ /* __typeof__(V) abbreviation */ #define TOF(V) __typeof__(V) /* Expand variables list to list of typeof and variable names */ #define TO3(_0,_1,_2,_3) TOF(_0) v0; TOF(_1) v1; TOF(_2) v2; TOF(_3) v3; #define TO2(_0,_1,_2) TOF(_0) v0; TOF(_1) v1; TOF(_2) v2; #define TO1(_0,_1) TOF(_0) v0; TOF(_1) v1; #define TO0(_0) TOF(_0) v0; #define TO_(_0,_1,_2,_3,TO_MACRO,...) TO_MACRO #define TO(...) TO_(__VA_ARGS__,TO3,TO2,TO1,TO0)(__VA_ARGS__) /* Assign to multitype */ #define MTA3(_0,_1,_2,_3) _0 = mtr.v0; _1 = mtr.v1; _2 = mtr.v2; _3 = mtr.v3; #define MTA2(_0,_1,_2) _0 = mtr.v0; _1 = mtr.v1; _2 = mtr.v2; #define MTA1(_0,_1) _0 = mtr.v0; _1 = mtr.v1; #define MTA0(_0) _0 = mtr.v0; #define MTA_(_0,_1,_2,_3,MTA_MACRO,...) MTA_MACRO #define MTA(...) MTA_(__VA_ARGS__,MTA3,MTA2,MTA1,MTA0)(__VA_ARGS__) /* Return multitype if multiple arguments, return normally if only one */ #define MTR1(...) { \ typedef struct mtr_s { \ TO(__VA_ARGS__) \ } mtr_t; \ mtr_t *mtr = malloc(sizeof(mtr_t)); \ *mtr = (mtr_t){__VA_ARGS__}; \ return mtr; \ } #define MTR0(_0) return(_0) #define MTR_(_0,_1,_2,_3,MTR_MACRO,...) MTR_MACRO /* ============================== API MACROS =============================== */ /* Declare return type before function */ typedef void* multitype; #define multitype(...) multitype /* Assign return values to variables */ #define let(...) \ for(int mti = 0; !mti;) \ for(multitype mt; mti < 2; mti++) \ if(mti) { \ typedef struct mtr_s { \ TO(__VA_ARGS__) \ } mtr_t; \ mtr_t mtr = *(mtr_t*)mt; \ MTA(__VA_ARGS__) \ free(mt); \ } else \ mt /* Return */ #define RETURN(...) MTR_(__VA_ARGS__,MTR1,MTR1,MTR1,MTR0)(__VA_ARGS__) 

Cela permet de retourner jusqu'à quatre variables d'une fonction et de les affecter à quatre variables au maximum. Par exemple, vous pouvez les utiliser comme ceci:

 multitype (int,float,double) fun() { int a = 55; float b = 3.9; double c = 24.15; RETURN (a,b,c); } int main(int argc, char *argv[]) { int x; float y; double z; let (x,y,z) = fun(); printf("(%d, %f, %g\n)", x, y, z); return 0; } 

C'est ce qu'il imprime:

 (55, 3.9, 24.15) 

La solution peut ne pas être aussi portable car elle nécessite C99 ou une version ultérieure pour les macros variadiques et les déclarations de variables pour les instructions. Mais je pense que c'était assez intéressant pour poster ici. Un autre problème est que le compilateur ne vous avertira pas si vous leur atsortingbuez des valeurs incorrectes, vous devez donc faire attention.

Des exemples supplémentaires et une version basée sur la stack du code utilisant des unions sont disponibles dans mon référentiel github .

Hey Peter je crois que vous pouvez retourner 2 valeurs à l’aide de pointeurs en C.