Une approche consiste à utiliser des macros. Placez-le dans un fichier d'en-têtemultitype.h
#include <stdlib.h>
#define TOF(V) __typeof__(V)
#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__)
#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__)
#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
typedef void* multitype;
#define multitype(...) multitype
#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
#define RETURN(...) MTR_(__VA_ARGS__,MTR1,MTR1,MTR1,MTR0)(__VA_ARGS__)
Cela permet de renvoyer jusqu'à quatre variables à partir d'une fonction et de les affecter à jusqu'à quatre variables. À titre d'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;
}
Voici ce qu'il imprime:
(55, 3.9, 24.15)
La solution n'est peut-être pas aussi portable car elle nécessite C99 ou une version ultérieure pour les macros variadiques et les déclarations de variables for-statement. 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 attribuez des valeurs incorrectes, vous devez donc faire attention.
Des exemples supplémentaires et une version basée sur la pile du code utilisant des unions sont disponibles sur mon référentiel github .
string
voulez-vous dire "J'utilise C ++ et c'est lastd::string
classe" ou "J'utilise C et ceci est unchar *
pointeur ou unchar[]
tableau."