Variable no d’argument dans C Macro

J’écris du code spécifique au matériel, où je veux utiliser des macros C, la définition de la macro serait quelque chose comme ceci: –

#define VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1) if(a[MODE][RESOURCE1] != x1) || \ (a[MODE][RESOURCE1] != y1)) \ a[MODE][RESOURCE1]=x3; 

Depuis quelque temps, je peux avoir plus d’une ressource à atsortingbuer, par exemple: –

 #define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2) if(a[MODE][RESOURCE1] != x1) || \ (a[MODE][RESOURCE1] != y1)) \ a[MODE][RESOURCE1]=x3; if(a[MODE][RESOURCE2] != x1) || \ (a[MODE][RESOURCE2] != y1)) \ a[MODE][RESOURCE2]=x3; 

Est-il possible d’écrire une macro, qui couvre les deux cas, car il faut un nombre variable d’arguments?

J’ai utilisé un nombre variable d’arguments, en macro pour les macros printf, mais ensuite comment je vais traiter ces arguments, par leur nom respectif, par exemple si je modifie la définition MACRO telle que: 0-

 #define VALIDA_RESOURCE_AND_ALLOCATE(MODE,.....) 

Comment vais-je identifier RESOURCE1, RESOURCE2?

Vos macros contiennent beaucoup de code répété. Les simplifier consortingbue à rendre la solution plus évidente:

 #define VALIDATE_RESOURCE_AND_ALLOCATE_1(MODE,RESOURCE1,RESOURCE2) do {\ VALIDATE_RESOURCE_AND_ALLOCATE(MODE, RESOURCE1); \ VALIDATE_RESOURCE_AND_ALLOCATE(MODE, RESOURCE2); \ } while(0) 

Ici, il est plus clair que ceci est simplement une invocation répétée de la première macro en parcourant une liste d’arguments.

En supposant que vous sachiez que les types de données utilisés ici seront toujours cohérents, vous pouvez essayer quelque chose comme ça (non testé et écrit du haut de ma tête):

 #ifdef HARDWARE_PLATFORM_A static sometype args[] = { RESOURCE1, RESOURCE2, /* ... etc, etc */ }; #elif defined HARDWARE_PLATFORM_B static sometype args[] = { RESOURCE10, RESOURCE11, /* ... etc, etc */ }; /* repeat for all hardware platforms */ #endif void initialization_function (void) { int i; for (i = 0; i < (sizeof(args) / sizeof(args[0])); ++i) { VALIDATE_RESOURCE_AND_ALLOCATE(MODE, args[i]); } } 

sometype est le type de données des arguments que vous utiliserez pour RESOURCE1 , RESOURCE2 , etc.

Étant donné la complexité de ce que vous essayez de faire, vous feriez mieux d'écrire une fonction pour faire l'itération au lieu d'une macro. Vous pouvez toujours utiliser une macro pour créer la liste RESOURCE , mais n'essayez pas de faire en sorte que le préprocesseur effectue l'itération pour vous. Si vous avez besoin d'éviter la surcharge d'un appel de fonction (puisque vous l'avez balisé comme "incorporé"), vous pouvez déclarer les fonctions en inline et le résultat doit être aussi efficace que l'utilisation d'une macro. Dans le processus, cependant, vous gagnerez des choses comme la sécurité de type.

Bien qu’il soit techniquement possible de le faire avec une macro, ce serait un désagrément qui entraînerait probablement plus de problèmes que d’avantages. Faire des tâches procédurales complexes avec le pré-processeur s'avère rarement satisfaisant.

L'autre alternative est d'utiliser un générateur de code qui prend une liste d'arguments RESOURCE partir d'un fichier et génère un fichier .c contenant le code d'initialisation. Le générateur de code serait écrit dans un langage beaucoup plus puissant que le pré-processeur C (presque n'importe quel langage de script pourrait être utilisé ici). Cela ne vaut probablement pas la peine à moins que vous ayez une longue liste de RESOURCE , cependant.

Une façon de le faire est de ne pas transmettre un nombre variable d’arguments, mais de s’en tenir à deux et de faire en sorte que la seconde soit une liste pouvant être utilisée dans une initialisation. Par exemple (les barres obliques inverses laissées pour plus de clarté):

 #define VALIDATE_RESOURCE_AND_ALLOCATE(MODE, LIST) { int resources[] = LIST; int count; for(count = 0; count < sizeof(resources)/sizeof(int); count++) { /* do stuff here for each resources[count] */ } } 

Et puis vous pouvez simplement l'appeler comme tel:

 VALIDATE_RESOURCE_AND_ALLOCATE(MODE, { RESOURCE1, RESOURCE2 } ) 

Remarque: il y a plus d'une façon de peler ce chat, alors choisissez votre réponse préférée et allez-y 🙂

Serait-ce trop bête? 😉

 #define VALIDATE_RESOURCE_AND_ALLOCATE(MODE,RESOURCE1,RESOURCE2) \ if(a[MODE][RESOURCE1] != x1) || (a[MODE][RESOURCE1] != y1)) \ a[MODE][RESOURCE1]=x3; \ if((RESOURCE1 != RESOURCE2) && (a[MODE][RESOURCE2] != x1) || (a[MODE][RESOURCE2] != y1))) \ a[MODE][RESOURCE2]=x3; 

et appelez-le comme ci-dessous pour une seule ressource

 VALIDATE_RESOURCE_AND_ALLOCATE(M1,R1,R1) 

et comme ci-dessous pour deux?

 VALIDATE_RESOURCE_AND_ALLOCATE(M1,R1,R2)