web-dev-qa-db-fra.com

Passer une ellipse à une autre fonction variadique

J'ai environ 30 fonctions variadiques. Chacun accepte un chemin comme argument final, par exemple:

bool do_foo(struct *f, int q, const char *fmt, ...)

Dans chaque fonction, je dois vérifier que le format étendu est inférieur ou égal à une certaine taille. Donc, je me retrouve à copier/coller le même morceau de code pour vérifier le nombre de caractères que vsnprintf() n'a pas imprimés, définir errno en conséquence et renoncer à l'écriture.

Ce que je voudrais faire, c'est écrire une fonction pour ce faire, qui retournerait une chaîne allouée statiquement (étendue) qui est connue pour être une taille sûre, ou une chaîne nouvellement initialisée en cas d'échec, qui pourrait être vérifiée par rapport à NULL. Les vérifications doivent également déterminer si la chaîne est un chemin absolu ou relatif, ce qui influence la taille sûre de la chaîne. C'est beaucoup de code en double et ça commence à sentir.

Existe-t-il un moyen de transmettre le contenu de l'élipse de l'entrée de ma fonction à une autre fonction? Ou dois-je d'abord appeler va_start(), puis passer le va_list À la fonction d'assistance?

Modifier:

Je ne suis pas du tout opposé à passer le va_list À l'assistant, je voulais juste m'assurer que rien d'autre n'existait. Il me semble que le compilateur comprend où commencent les arguments variadiques, donc j'étais simplement curieux de pouvoir lui dire de les transmettre.

66
Tim Post

Vous ne pouvez pas, vous pouvez uniquement passer les arguments sous la forme d'un va_list. Voir le FAQ comp.lang.c .

En général, si vous écrivez des fonctions variadiques (c'est-à-dire des fonctions qui prennent un nombre variable d'arguments) en C, vous devez écrire deux versions de chaque fonction: une qui prend des points de suspension (...), et celui qui prend un va_list. La version prenant un Ellipsis doit appeler va_start, appelez la version en prenant va_list, appel va_end, et revenez. Il n'y a pas besoin de duplication de code entre les deux versions de la fonction, car l'une appelle l'autre.

69
Adam Rosenfield

Vous pouvez probablement utiliser des macros variadiques - comme ceci:

#define FOO(...)  do { do_some_checks; myfun(__VA_ARGS__); } while (0)

NB! Les macros variadiques sont uniquement C99

10
qrdl

Je ne sais pas si cela vous aidera, vous pouvez accéder aux variables par référence. C'est une sorte d'astuce sournoise, mais cela ne vous permettra malheureusement pas d'utiliser Ellipsis dans la définition finale de la fonction.

#include <stdio.h>

void print_vars(int *n)
{
  int i;
  for(i=0;i<=*n;i++)
    printf("%X %d  ", (int)(n+i), *(n+i));
  printf("\n");
}

void pass_vars(int n, ...)
{
  print_vars(&n);
}

int main()
{
    pass_vars(4, 6, 7, 8, 0);
    return 0;
}

Sur mon PC, il produit

$ ./a.out
BFFEB0B0 4  BFFEB0B4 6  BFFEB0B8 7  BFFEB0BC 8  BFFEB0C0 0
1
Sepero

Vous devez transmettre va_list à l'assistant.

0
Andrew Grant