L’Annexe B du Manuel de référence C décrit les deux fonctions setjmp
et longjmp
pour ce que l’on appelle des sauts non locaux . Mis à part la compréhension de base que setjmp
enregistre les informations d’état et que longjmp restaure l’ state
, je n’ai pas été en mesure de comprendre le déroulement exact et les cas d’utilisation de cette fonctionnalité.
Alors, qu’est-ce que cette fonctionnalité accomplit exactement et où est-elle utile?
En ce qui concerne le stream de contrôle: setjmp
retourne deux fois et longjmp
ne retourne jamais. Lorsque vous appelez setjmp
pour la première fois pour stocker l’environnement, il renvoie zéro et lorsque vous appelez longjmp
, le stream de contrôle passe à renvoyer de setjmp
avec la valeur fournie dans l’argument.
(Notez que setjmp
ne doit pas nécessairement être une fonction; il peut s’agir d’une macro. longjmp
est une fonction.)
Les cas d’utilisation sont généralement cités comme “traitement des erreurs” et “n’utilisez pas ces fonctions”.
Voici un petit exemple de stream de contrôle:
jmp_buf env; void foo() { longjmp(&env, 10); +---->----+ } | | | | int main() (entry)---+ ^ V { | | | if(setjmp(&env) == 0) | (= 0) | | (= 10) { | ^ | foo(); +---->----+ | } +---->----+ else | { | return 0; +--- (end) } }
Remarques:
Vous ne pouvez pas passer 0 à longjmp
. Si vous le faites, 1
est renvoyé par setjmp
.
Vous ne devez pas retourner de la fonction qui a appelé setjmp
avant le longjmp
correspondant. En d’autres termes, longjmp
doit uniquement être appelé au-dessus de setjmp
dans la stack d’appels.
(Merci à @wildplasser 🙂 Vous ne pouvez pas stocker le résultat de setjmp
. Si vous souhaitez revenir de différentes manières, vous pouvez utiliser un switch
, cependant:
switch (setjmp(&env)) { case 0: // first call case 2: // returned from longjmp(&env, 2) case 5: // returned from longjmp(&env, 5) // etc. }