ProgrammationDéveloppeur C

Parlez-nous de la façon dont les opérateurs logiques ET (&&) et OU (||) fonctionnent en C. Quelles sont les caractéristiques de l'évaluation par court-circuit ? Comment une compréhension incorrecte du comportement de ces opérateurs peut-elle entraîner des erreurs ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question :

Les opérateurs logiques && et || ont été introduits en C pour vérifier des conditions logiques complexes. Leur particularité est le support de l'évaluation par court-circuit : le deuxième opérande n'est pas évalué si le résultat peut être clairement déterminé par le premier.

Problème :

De nombreux programmeurs s'attendent à ce que les deux opérandes soient toujours évalués, ou utilisent incorrectement les effets secondaires du deuxième opérande, supposant qu'il sera nécessairement exécuté. En pratique, cela conduit à des erreurs, des fuites de ressources et des comportements inattendus.

Solution :

Comprendre le mécanisme de l'évaluation par court-circuit aide à construire des constructions sûres, notamment dans les vérifications de pointeurs, de ressources et de fichiers. L'utilisation des effets secondaires dans la partie droite de l'expression doit être faite en toute connaissance de cause. Exemple de vérification sûre :

if (ptr && ptr->field) { /* ... */ }

Caractéristiques clés :

  • && et || utilisent la règle de 'court-circuit' : le deuxième opérande est évalué seulement si le résultat n'est pas déterminé après le premier.
  • Le court-circuit permet d'éviter l'accès à des pointeurs nuls, la division par zéro et d'autres situations dangereuses.
  • Des erreurs surviennent lors de l'imbrication d'expressions avec des effets secondaires, lorsque la partie droite peut ne pas être exécutée du tout.

Questions pièges.

L'expression f() sera-t-elle exécutée dans le fragment : if (0 && f()) ?

Non, la fonction f() ne sera pas appelée, car le résultat est déjà clair - l'expression est fausse, un calcul ultérieur est inutile.

Et dans l'instruction suivante : if (1 || f()) ?

Encore une fois, f() ne sera pas appelée : le résultat est déjà vrai après le premier opérande.

Peut-on utiliser les opérateurs && et || pour contrôler l'ordre d'exécution des fonctions avec des effets secondaires ?

Techniquement, c'est possible, mais une telle gestion conduit à un code illisible et instable. Il vaut mieux écrire explicitement l'ordre d'appel des fonctions, sans compter sur le comportement par court-circuit pour les effets secondaires.

Erreurs typiques et anti-patterns

  • Utilisation des effets secondaires dans la partie droite des expressions dans l'espoir qu'ils seront nécessairement exécutés.
  • Absence de vérification sur NULL avant de déréférencer un pointeur.
  • Conditions complexes imbriquées, rendant difficile la compréhension de l'ordre d'évaluation.

Exemple de la vie réelle

Cas négatif

if (flag || process()) { // ... }

Le processus ne sera jamais appelé si flag est vrai.

Avantages:

  • Protection contre un travail inutile.

Inconvénients:

  • Les effets secondaires ne se produisent pas quand ils étaient attendus, ce qui entraîne un bug.

Cas positif

if (!flag) process();

Avantages:

  • Code lisible, sûr et prévisible.

Inconvénients:

  • Un peu plus de lignes, nécessite un contrôle plus explicite, mais la lisibilité et la prévisibilité augmentent.