Comment empêcher la fonction d’imprimer?

Est-il possible de faire taire une fonction? Par exemple:

#include  int function(){ printf("BLAH!"); return 10; } int main(){ printf("%d", silence( function()) ); return 0; } 

Et au lieu de:

 BLAH! 10 

Je voudrais obtenir:

 10 

C’est possible? Si positif, comment le faire?

Une façon extrêmement compliquée de faire presque ce que vous voulez est d’utiliser l’appel système de dup2 () . Cela nécessite l’exécution de fflush(stdout); dup2(silentfd, stdout); fflush(stdout); dup2(silentfd, stdout); avant que la function() soit appelée, et la copie ensuite: fflush(stdout); dup2(savedstdoutfd, stdout); fflush(stdout); dup2(savedstdoutfd, stdout); . Il n’est donc pas possible de faire en silence(function()) , car cette construction ne permet d’exécuter du code qu’après que function() a déjà été exécuté.

Les descripteurs de fichier silentfd et savedstdoutfd doivent être préparés à l’avance (code non testé):

  int silentfd = open("/dev/null",O_WRONLY); int savedstdoutfd = dup(stdout); 

Ce n’est certainement pas ce que vous voulez vraiment, mais dans la mesure où votre question est formulée comme suit: «est-ce possible?», La réponse est «presque».

utilise la fonction macro et le périphérique nul.

Par exemple pour les fenêtres

 #include  #define silence(x) (_stream = freopen("NUL:", "w", stdout), _ret_value = x,_stream = freopen("CON:", "w", stdout),_ret_value) int _ret_value; FILE *_stream; int function(){ printf("BLAH!"); return 10; } int main(void){ printf("%d", silence( function()) ); return 0; } 

Non ce n’est pas possible. Vous pouvez toutefois essayer de redirect temporairement la sortie standard vers quelque chose d’autre. Cela peut être proche de ce que vous voulez.

Vous pouvez utiliser cette macro au lieu de printf pour pouvoir empêcher l’impression:

 int flag=0; #define PRINT(...) if(flag){printf(...)} 

utilisez ensuite la macro PRINT en considérant le flag variable. Si flag==1 , la fonction sera imprimée et si flag==0 , la fonction ne sera pas imprimée.

Avec les extensions GCC , vous pouvez envisager d’avoir des macros telles que

 bool silent; #define silence(X) ({int _x; quiet(); _x = (X); verbose(); _x; }) #define printf(Fmt,...) \ do{if (!silent) printf(Fmt,##__VA_ARGS__);}while(0) 

cette macro silence ne fonctionnerait que si son argument X est une expression int (ou use typeof ) Je suppose également que le résultat de printf n’est jamais utilisé. Rappelez-vous que les macros “récursives” sont spécialement pré-traitées, l’occurrence interne de printf (dans cette macro printf ) est laissée telle printf sans expansion de macro.

Notez que le silence ne peut pas être une fonction (sinon, son argument aurait été évalué avant de l’appeler). Et vous avez besoin de l’extension des expressions d’instruction GCC pour “mémoriser” le résultat de l’argument dans une variable _x (vous pouvez générer ce nom à l’aide de __COUNTER__ et de la concaténation du préprocesseur) afin de le restituer comme valeur de l’appel de macro silence .

Ensuite, vous devez définir vos fonctions quiet() et verbose() , par exemple

 void quiet() { silent = true; } void verbose() { silent = false, } 

si vous ne voulez pas définir printf comme votre macro, vous pouvez utiliser freopen (3) sur stdout (peut-être avec "/dev/null" etc …) ou faire des trucs dup2 (2) (comme suggéré par Pascal Cuoq ) .

Si votre base de code est énorme, et que vous voulez quelque chose de plus sérieux et que vous êtes prêt à passer des jours ou des semaines de travail, pensez à personnaliser votre compilateur GCC avec un plugin ou une extension MELT (ou demandez à quelqu’un de le faire). Notez que printf est connu de GCC.

En réalité, vous devriez définir votre propre macro comme

 #define myprintf(Fmt, ...) do{if (!silent) \ printf(Fmt,__VA_ARGS__);}while(0) 

et utilisez simplement myprintf au lieu de printf partout, c’est un truc portable. Bien entendu, je suppose que vous ne transmettez pas printf tant que pointeur de fonction.

Pour le débogage, je recommande en fait

 #define dbgprintf(Fmt,...) do{if (wantdebug) \ printf("%s:%d:" Fmt "\n", __FILE__, __LINE__, \ ##__VA_ARGS__);}while(0) 

et puis j’utilise dbgprintf("i=%d",i) ou simplement dbgprintf("foo here") dans mon code.

J’utilise ##__VA_ARGS__ qui est une extension GCC pour ne pas accepter d’arguments variables pour une macro variadique. Si vous voulez un code C99 ssortingct, vous devrez simplement indiquer __VA_ARGS__ et chaque dbgprintf aurait besoin d’un argument après le format.

Vous pouvez également ré-implémenter votre propre fonction printf , mais je ne conseille pas de le faire.

(Notez que les choses pourraient être plus complexes, vous pouvez imprimer en utilisant fputs not printf ….)

Si vous concevez la fonction, procédez comme suit:

 int function(void (*printer)(char *)){ if (!printer) printer = printf; printer("BLAH!"); return 10; } void silence(char *s){ return; } int main(int argc, char **argv){ printf("%d\n", function(silence)); return 0; } 

Cela devrait faire ce que vous cherchez. Malheureusement, je ne l’ai pas testé et mon C est probablement un peu rouillé.

Bien sûr, si vous ne contrôlez pas la fonction, les réponses déjà affichées sont toutes des solutions correctes.


En fait, si vous concevez vous-même la fonction, faites simplement:

 int function(int print){ if (print) printf("BLAH!"); return 10; } function(0); /* Won't print anything */ function(!0); /* Will print "BLAH!" */ 

parce que 0 est faux et que toute valeur non nulle (ou !0 ) est vraie. Ma suggestion ci-dessus est sujette aux erreurs car vous devrez pouvoir imiter la signature printf pour le silence ou pour toute autre fonction que vous souhaitez utiliser.

Malheureusement, si vous utilisez explicitement la fonction et que vous l’appelez ainsi, elle sera toujours imprimée. si vous souhaitez désactiver complètement la fonction, vous pouvez simplement commenter cette ligne. Vous pouvez même utiliser une instruction de contrôle afin qu’elle ne soit imprimée que si et si une condition est remplie, sinon elle rest vide et ne renvoie que le numéro.