A quoi sert faire do (0) quand on définit une macro?

Duplication possible:
Instructions Do-While et if-else dans les macros C / C ++

Je lis le kernel Linux et j’ai trouvé beaucoup de macros comme ceci:

#define INIT_LIST_HEAD(ptr) do { \ (ptr)->next = (ptr); (ptr)->prev = (ptr); \ } while (0) 

Pourquoi l’utilisent-ils plutôt que de le définir simplement dans un {}?

Vous pouvez le suivre avec un point-virgule et le faire ressembler à une fonction. Cela fonctionne aussi avec les clauses if / else correctement.

Sans le temps (0), votre code ci-dessus ne fonctionnerait pas avec

 if (doit) INIT_LIST_HEAD(x); else displayError(x); 

puisque le point-virgule après la macro “mangerait” la clause else, et ce qui précède ne comstackrait même pas.

Il vous permet de regrouper plusieurs instructions en une seule macro.

Supposons que vous ayez fait quelque chose comme:

 if (foo) INIT_LIST_HEAD(bar); 

Si la macro a été définie sans encapsulation, faites {…} while (0) ;, le code ci-dessus sera étendu à

 if (foo) (bar)->next = (bar); (bar)->prev = (bar); 

Ce n’est clairement pas ce qui était prévu, car seule la première déclaration sera exécutée si foo tient. La seconde instruction serait exécutée indépendamment du fait que foo tienne ou non.

Edit: Plus d’explications sur http://c-faq.com/cpp/multistmt.html et http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Swallowing-the-Semicolon.html # Avaler le point-virgule