web-dev-qa-db-fra.com

Quel est le but d'un bloc 'if (0)' dans le bloc if-else?

Ma question concerne la ligne que j'ai mentionnée dans le sujet et que je peux voir à de nombreux endroits dans le code de production.

Le code général ressemble à ceci:

if (0) {
    // Empty braces
} else if (some_fn_call()) {
    // actual code
} else if (some_other_fn_call()) {
    // another actual code
    ...
} else {
    // default case
}

Les autres branches ne sont pas pertinentes pour ma question. Je me demande quelle est la signification de mettre if (0) ici. Les accolades sont vides, donc je ne pense pas qu'il soit supposé commenter un bloc de code. Est-ce que cela oblige le compilateur à optimiser ou est-ce que ses intentions sont différentes?

J'ai essayé de rechercher ce cas explicite ici sur SO et sur Internet, mais sans succès. Il y a des questions similaires à propos de JavaScript, mais pas C. Il y a une autre question, Que se passe-t-il lorsqu'un zéro est assigné dans une "condition if"? , mais il traite de l'affectation nulle à une variable, pas le " si (0) 'utilisation elle-même.

140
Zzaponka

J'utilise parfois cela pour des raisons de symétrie afin de pouvoir déplacer l'autre else if{ librement avec l'éditeur sans avoir à me soucier de la première if.

Sémantiquement le

if (0) {
    // Empty braces
} else 

partie ne fait rien et vous pouvez compter sur les optimiseurs pour le supprimer.

90
PSkocik

Cela peut être utile s’il existe des instructions #if,

   if (0)
   {
       // Empty block
   }
#if TEST1_ENABLED
   else if (test1())
   {
      action1();
   }
#endif
#if TEST2_ENABLED
   else if (test2())
   {
      action2();
   }
#endif

etc.

Dans ce cas, tous les tests (et tous) peuvent être #if 'édités, et le code sera compilé correctement. Presque tous les compilateurs vont supprimer la partie if (0) {}. Un simple générateur automatique pourrait générer un code comme celui-ci, car il est légèrement plus facile à coder - il n'est pas nécessaire de considérer le premier bloc activé séparément.

104
CSM

J'ai vu un modèle similaire utilisé dans le code généré. Par exemple, en SQL, j'ai vu des bibliothèques émettre la clause where suivante.

where 1 = 1

Cela facilite probablement l'ajout d'autres critères, car tous les critères supplémentaires peuvent être précédés de and au lieu d'un contrôle supplémentaire pour déterminer s'il s'agit du premier critère ou non.

44
Seth Flowers

Comme écrit, la clause if (0) {} ne compile rien.

Je suppose que la fonction de la clause en haut de cette échelle est de fournir un endroit facile pour désactiver temporairement toutes les autres fonctionnalités en même temps (à des fins de débogage ou de comparaison) en remplaçant le 0 par un 1 ou true.

43
Russell Borogove

Une possibilité qui n’a pas encore été mentionnée: la ligne if (0) { pourrait être un endroit pratique pour un point de rupture.

Le débogage est souvent effectué sur du code non optimisé afin que le test toujours faux soit présent et puisse avoir un point d'arrêt défini. Une fois compilé pour la production, la ligne de code serait optimisée. Cette ligne apparemment inutile fournit des fonctionnalités pour les versions de développement et de test sans impact sur les versions validées.

Il y a aussi d'autres bonnes suggestions ci-dessus; la seule façon de vraiment savoir quel est le but est de retrouver l'auteur et de demander. Votre système de contrôle de code source pourrait vous aider. (Recherchez la fonctionnalité de type blame-.)

15
studog

Je ne suis pas sûr des optimisations, mais mes deux cents:

Cela est dû à une modification du code, dans laquelle une condition principale a été supprimée (l'appel de la fonction dans le bloc initial if, par exemple), mais les développeurs/responsables

ainsi, au lieu de supprimer le bloc associé if, ils ont simplement changé la condition en if(0), puis sont passés à autre chose.

15
Sourav Ghosh

C'est du code pourri.

À un moment donné, "si" a fait quelque chose d'utile, la situation a changé, peut-être que la variable évaluée a été supprimée.

La personne qui réparait/changeait le système le faisait le moins possible pour affecter la logique du système alors il s'est assuré que le code serait recompilé. Donc, il laisse un "if (0)" parce que c'est rapide et facile et qu'il n'est pas totalement sûr que c'est ce qu'il veut faire. Il fait fonctionner le système et ne retourne pas le réparer complètement.

Ensuite, le prochain développeur arrive et pense que cela a été fait délibérément et ne commente que cette partie du code (étant donné qu'elle n'est pas évaluée de toute façon), la prochaine fois que le code sera touché, ces commentaires seront supprimés.

15
Dark Matter

J'ai vu des blocs de code non accessibles en JavaScript pré-développé qui ont été générés à l'aide d'un langage de modélisation.

Par exemple, le code que vous lisez peut avoir été collé à partir d'un serveur qui a pré-évalué la première condition qui, à ce moment-là, reposait sur une variable uniquement disponible côté serveur.

if ( ${requestIsNotHttps} ){ ... }else if( ...

qui déjà une fois pré-compilé:

if ( 0 ){ ... }else if ( ...

j'espère que cela vous aidera à relativiser la faible activité potentielle du clavier de l'ère des codeurs pro-recyclage pour laquelle je manifeste un enthousiasme!

9
simonarame

Cette construction peut également être utilisée en C pour implémenter une programmation générique avec le type safety, en s’appuyant sur le fait que le code inaccessible est toujours vérifié par le compilateur:

// this is a generic unsafe function, that will call fun(arg) at a later time
void defer(void *fun, void *arg);

// this is a macro that makes it safer, by checking the argument
// matches the function signature
#define DEFER(f, arg) \
   if(0) f(arg); \              // never actually called, but compile-time checked
   else defer(f, (void *)arg);  // do the unsafe call after safety check

void myfunction(int *p);

DEFER(myfunction, 42);     // compile error
int *b;
DEFER(myfunction, b);      // compiles OK
8
philfr

Je pense que c'est juste un mauvais code. En écrivant un exemple rapide dans Compiler Explorer, nous voyons qu’à la fois dans gcc et clang, aucun code n’est généré pour le bloc if (0), même avec les optimisations complètement désactivées:

https://godbolt.org/z/PETIks

Jouer avec supprimer la if (0) ne provoque aucune modification du code généré, je conclus donc qu'il ne s'agit pas d'une optimisation.

Il est possible qu’il y ait eu quelque chose dans le bloc supérieur if qui a ensuite été supprimé. En bref, il semble que le supprimer entraînerait la génération exacte du même code, alors n'hésitez pas à le faire.

6
cha0site

Comme il a été dit, le zéro est évalué à faux et la branche sera probablement optimisée par le compilateur.

J'ai déjà vu cela auparavant dans le code lorsqu'une nouvelle fonctionnalité a été ajoutée et qu'un kill-switch était nécessaire (si quelque chose ne va pas avec la fonctionnalité, vous pouvez simplement l'éteindre), et quelque temps plus tard, lorsque le kill-switch a été supprimé. le programmeur n'a pas également supprimé la branche, par exemple.

if (feature_a_active()) {
    use_feature_a();
} else if (some_fn()) {
   ...

devenu

if (0) {
   // empty
} else if (some_fn()) {
   ...
6
sergiopm

La réponse de @ PSkocik est correcte, mais j'ajoute mes deux sous. Je ne sais pas si je devrais le faire comme commentaire ou comme réponse. choisir ce dernier, parce que mon humble avis vaut le voir, alors que les commentaires sont souvent invisibles.

Non seulement j'utilise occasionnellement

if(0) {
   //deliberately left empty
} else if( cond1 ) {
   //deliberately left empty
} else if( cond2 ) {
   //deliberately left empty
...
} else {
   // no conditions matched
}

Mais je fais aussi de temps en temps

if( 1 
    && cond1 
    && cond2
    ...
    && condN
) {

ou

if( 0 
    || cond1 
    || cond2
    ...
    || condN
) {

pour des conditions compliquées. Pour les mêmes raisons - plus facile à modifier, # ifdef, etc.

D'ailleurs, en Perl je ferai

@array = (  
    elem1,
    elem2,
    ...
    elem1,
) {
  • notez la virgule à la fin de la liste. J'oublie si les virgules sont des séparateurs ou des délimiteurs dans les listes C et C++. IMHO c'est une chose que nous avons apprise: [ Les virgules finales en Perl sont-elles une mauvaise pratique? les virgules] sont une bonne chose. Comme toute nouvelle notation, il faut un certain temps pour s'y habituer.

Je compare le code if(0) à LISP

(cond   (test1    action1)
   (test2    action2)
   ...
   (testn   actionn))

que vous avez deviné, je peux indenter comme

(cond   
   (test1    action1)
   (test2    action2)
   ...
   (testn   actionn)
)

J'ai parfois essayé d'imaginer à quoi pourrait ressembler une syntaxe plus lisible par l'homme.

Peut-être

IF
:: cond1 THEN code1
:: cond2 THEN code2
...
:: condN THEN codeN
FI

inspiré par le [ https://en.wikipedia.org/fr/Guarded_Command_Language#Selection:_if] [Langage de commande gardé ].

Mais cette syntaxe implique que les conditions soient évaluées en parallèle, alors que if...else-if implique une évaluation séquentielle et priorisée des conditions.

J'ai commencé à faire ce genre de chose en écrivant des programmes générant d'autres programmes, où c'est particulièrement pratique.

Pendant que nous y sommes, en écrivant RTL en utilisant le vieil iHDL d’Intel, j’ai codé des choses comme

   IF 0 THEN /*nothing*/
   **FORC i FROM 1 TO 10 DOC** 
   ELSE IF signal%i% THEN    
      // stuff to do if signal%i% is active
   **ENDC** 
   ELSE   
      // nothing matched 
   ENDIF

FORC..DOC..ENDC est une construction de boucle de préprocesseur de macro, qui se développe en

   IF 0 THEN /*nothing*/
   ELSE IF signal1 THEN    
      // stuff to do if signal1 is active
   ELSE IF signal2 THEN    
      // stuff to do if signal2 is active
   ...
   ELSE IF signal100 THEN    
      // stuff to do if signal100 is active
   ELSE   
      // nothing matched 
   ENDIF

Il s'agissait d'un code unique, non impératif, de sorte que la définition d'une variable d'état n'était pas autorisée, si vous deviez effectuer des opérations telles que rechercher le premier bit défini.

   IF 0 THEN /*nothing*/
   ELSE IF signal1 THEN    
      found := 1
   ELSE IF signal2 THEN    
      found := 2
   ...
   ELSE IF signal100 THEN    
      found := 100
   ELSE   
      // nothing matched 
   ENDIF

À bien y penser, c’est peut-être le premier endroit où j’ai rencontré de telles constructions.

BTW, les objections que certains avaient au style if (0) - que les conditions else-if-if sont séquentiellement dépendantes et ne peuvent pas être réorganisées arbitrairement - ne s'appliquent pas à AND et OR et XOR la logique dans RTL - mais s’applique aux courts-circuits && et ||.

1
Krazy Glew
    Actually according to my opinion, if we put any variable for checking inside
    e.g:-
public static void main(string args[])
{
        var status;
        var empList=_unitofWork.EmpRepository.Get(con=>con.isRetired==true);
        //some code logic 
        if(empList.count>0)
        {
          status=true;
        }
        if(status)
        {
         //do something
        }
        else
        {
        //do something else
        }
}
     if then its dynamically get the value in run time and invoke the logic inside it, else its simply extra line of code i guess.

    Anybody have any depth knowledge why this thing is used....or agree with me.
    kindly respond. 
1

Il est utile de déboguer ce bloc en mettant simplement le bloc 1. Ceci désactive toutes les fonctionnalités du bloc si autrement. Et nous pouvons également élargir le bloc if else.

1
Abdul Ahad Sheikh