linux syntaxe - Pourquoi certains programmeurs de noyau utilisent-ils goto au lieu de simples boucles while?





programmation (3)


Contexte historique: Nous devons nous rappeler que Dijkstra a écrit Goto Considered Harmful en 1968, quand beaucoup de programmeurs utilisaient goto en remplacement de la programmation structurée ( if , while , for , etc.).

C'est 44 ans plus tard, et il est rare de trouver cette utilisation de goto dans la nature. La programmation structurée a déjà gagné, il y a longtemps.

Analyse de cas:

L'exemple de code ressemble à ceci:

    SETUP...
again:
    COMPUTE SOME VALUES...
    if (cmpxchg64(ptr, old_val, val) != old_val)
        goto again;

La version structurée ressemble à ceci:

SETUP...
do {
    COMPUTE SOME VALUES...
} while (cmpxchg64(ptr, old_val, val) != old_val);

Quand je regarde la version structurée, je pense immédiatement, "c'est une boucle". Quand je regarde la version de goto , je la vois comme une ligne droite avec un "try again" à la fin.

La version goto a SETUP et COMPUTE SOME VALUES sur la même colonne, ce qui souligne que la plupart du temps, le flux de contrôle passe à travers les deux. La version structurée met SETUP et COMPUTE SOME VALUES sur des colonnes différentes, ce qui souligne que le contrôle peut les traverser différemment.

La question ici est quel genre d'accent voulez-vous mettre dans le code? Vous pouvez comparer cela avec goto pour la gestion des erreurs:

Version structurée:

if (do_something() != ERR) {
    if (do_something2() != ERR) {
        if (do_something3() != ERR) {
            if (do_something4() != ERR) {
                ...

Aller à la version:

if (do_something() == ERR)  // Straight line
    goto error;             // |
if (do_something2() == ERR) // |
    goto error;             // |
if (do_something3() == ERR) // |
    goto error;             // V
if (do_something4() == ERR) // emphasizes normal control flow
    goto error;

Le code généré est fondamentalement le même, nous pouvons donc le considérer comme une préoccupation typographique, comme l'indentation.

Quand j'ai appris C, le professeur m'a dit toute la journée: "N'utilise pas le goto, c'est une mauvaise habitude, c'est moche, c'est dangereux!" etc.

Pourquoi alors certains programmeurs de noyau utilisent-ils goto , par exemple dans cette fonction , où il pourrait être remplacé par un simple

while(condition) {} 

ou

do {} while(condition);

Je ne peux pas comprendre ça. Est-il préférable dans certains cas d'utiliser goto au lieu de while / do - while ? Et si oui, pourquoi?




Dans le cas de cet exemple, je pense qu'il s'agissait de mettre à jour la prise en charge de SMP dans du code écrit à l'origine d'une manière non sécurisée par SMP. Ajouter un goto again; le chemin est beaucoup plus simple et moins invasive que la restructuration de la fonction.

Je ne peux pas dire que j'aime beaucoup ce style, mais je pense aussi qu'il est malavisé d'éviter goto pour des raisons idéologiques. Un cas particulier d'utilisation de goto (différent de cet exemple) est où goto est seulement utilisé pour avancer dans une fonction, jamais en arrière. Cette classe d'utilisations n'aboutit jamais à des constructions de boucles issues de goto , et c'est presque toujours la manière la plus simple et la plus claire d'implémenter le comportement nécessaire (qui nettoie et retourne en général sur erreur).




Vérifiez le code ci-dessous,

    int x=0;
    int temp=x++;
    System.out.println("temp = "+temp);
    x = temp;
    System.out.println("x = "+x);

la sortie sera,

temp = 0
x = 0

post increment moyens post increment incrémentent la valeur et renvoient la valeur avant l'incrément . C'est pourquoi la valeur temp est 0 . Alors que faire si temp = i et c'est dans une boucle (sauf pour la première ligne de code). juste comme dans la question !!!!





c linux loops linux-kernel goto