doe {…} while(false)

Ik keek naar een code van een persoon en merkte dat hij een patroon in zijn functies lijkt te hebben:

<return-type> function(<params>)
{
 <initialization>
 do
 {
   <main code for function>
 }
 while(false);
 <tidy-up & return>
}

Het is niet slecht, meer eigenaardig (de eigenlijke code is redelijk netjes en niet verrassend). Het is niet iets dat ik eerder heb gezien en ik vroeg me af of iemand een logica erachter kan bedenken – achtergrond in een andere taal misschien?


Antwoord 1, autoriteit 100%

Je kunt breakuit do{...}while(false).


Antwoord 2, autoriteit 72%

Veel mensen wijzen erop dat het vaak met pauze wordt gebruikt als een ongemakkelijke manier om “goto” te schrijven. Dat is waarschijnlijk waar als het rechtstreeks in de functie wordt geschreven.

In een macro, OTOH, do { something; } while (false)een handige manier is om een ​​puntkomma te DWINGEN na de macro-aanroep, mag er absoluut geen ander token volgen.

En een andere mogelijkheid is dat er ofwel ooit een lus was, of dat iteratie in de toekomst naar verwachting zal worden toegevoegd (bijv. bij testgestuurde ontwikkeling was iteratie niet nodig om de tests te doorstaan, maar logischerwijs zou het logisch zijn om loop daarheen als de functie wat algemener moet zijn dan momenteel vereist)


Antwoord 3, autoriteit 14%

De breuk als goto is waarschijnlijk het antwoord, maar ik zal een ander idee naar voren brengen.

Misschien wilde hij een lokaal gedefinieerde variabele hebben en gebruikte hij deze constructie om een ​​nieuw bereik te krijgen.

Onthoud dat hoewel recente C++ overal {...}toestaat, dit niet altijd het geval was.


Antwoord 4, autoriteit 12%

Ik heb het gezien als een handig patroon wanneer er veel potentiële exitpunten voor de functie zijn, maar dezelfde opschoningscode is altijd vereist, ongeacht hoe de functie wordt afgesloten.

Het kan een vermoeiende if/else-if-boom een ​​stuk gemakkelijker leesbaar maken, door gewoon te breken wanneer een exit-punt wordt bereikt, met de rest van de logica achteraf.

Dit patroon is ook handig in talen die geen goto-statement hebben. Misschien heeft de oorspronkelijke programmeur daar het patroon geleerd.


Antwoord 5, autoriteit 6%

Ik heb dergelijke code gezien, zodat je breakals een soort gotokunt gebruiken.


Antwoord 6, autoriteit 6%

Ik denk dat het handiger is om breakte schrijven in plaats van goto end. Je hoeft niet eens een naam voor het label te bedenken wat de bedoeling duidelijker maakt: je wilt niet naar een label met een specifieke naam springen. Je wilt hier weg.

Ook is de kans groot dat je de beugel toch nodig hebt. Dit is dus de do{...}while(false);versie:

do {
   // code
   if (condition) break; // or continue
   // more code
} while(false);

En dit is de manier waarop je het zou moeten uitdrukken als je gotozou willen gebruiken:

{
   // code
   if (condition) goto end;
   // more code
}
end:

Ik denk dat de betekenis van de eerste versie veel gemakkelijker te begrijpen is. Het is ook gemakkelijker te schrijven, gemakkelijker uit te breiden, gemakkelijker te vertalen naar een taal die gotoniet ondersteunt, enz.


De meest genoemde zorg over het gebruik van breakis dat het een slecht vermomde gotois. Maar eigenlijk lijkt breakmeer op return: beide instructies springen uit een codeblok dat redelijk gestructureerd is in vergelijking met goto. Desalniettemin laten beide instructies meerdere uitgangen toe in een codeblok, wat soms verwarrend kan zijn. Ik zou immers proberen voor de meest duidelijke oplossing te gaan, wat dat ook is in de specifieke situatie.


Antwoord 7, autoriteit 5%

Dit is gewoon een perversie van whileom de sematica van goto tidy-upte krijgen zonder het woord goto te gebruiken.

Het is een slechte vorm, want als je otherloops gebruikt in de buitenste whilede breaksdubbelzinnig worden voor de lezer. “Moet dit naar de uitgang gaan? of is dit alleen bedoeld om uit de binnenste lus te breken?”


Antwoord 8, autoriteit 4%

Deze truc wordt gebruikt door programmeurs die te verlegen zijn om een ​​expliciete gotoin hun code te gebruiken. De auteur van de bovenstaande code wilde de mogelijkheid hebben om vanuit het midden van de code rechtstreeks naar het “opschonen en terugkeren”-punt te springen. Maar ze wilden geen label en expliciete gotogebruiken. In plaats daarvan kunnen ze een breakgebruiken in de hoofdtekst van de bovenstaande “nep”-cyclus om hetzelfde effect te bereiken.


Antwoord 9, autoriteit 4%

Het ziet eruit als een C-programmeur. In C++ hebben automatische variabelen destructors die u gebruikt om op te ruimen, dus er hoeft niets op te ruimen voor de terugkeer. In C had je dit RAII-idioom niet, dus als je algemene opschooncode hebt, je gotohet, of gebruik een eenmalige lus zoals hierboven.

Het grootste nadeel in vergelijking met het C++-idioom is dat het niet wordt opgeruimd als er een uitzondering in de body wordt gegooid. C had geen uitzonderingen, dus dit was geen probleem, maar het maakt het wel een slechte gewoonte in C++.


Antwoord 10, autoriteit 4%

Het is een veel voorkomende praktijk. In C. Ik probeer het te zien alsof je tegen jezelf wilt liegenop een manier “Ik gebruik geen goto“. Als je erover nadenkt, zou er niets mis zijn met een gotodie op dezelfde manier wordt gebruikt. In feite zou het ook het inspringingsniveau verminderen.

Dat gezegd hebbende, merkte ik echter dat deze do..while-loops vaak groter worden. En dan krijgen ze ifs en elses binnen, waardoor de code eigenlijk niet erg leesbaar, laat staan ​​testbaar wordt.

Die do..whilezijn normaal gesproken bedoeld om op te ruimen. Op alle mogelijke manieren zou ik liever RAIIgebruiken en vroeg terugkerenvan een kortefunctie. Aan de andere kant biedt Cu niet zoveel gemakken als C++, waardoor een do..whileeen van de beste benaderingen is om op te ruimen.


11

Ik denk dat dit wordt gedaan om te gebruiken breakof continueuitspraken. Een soort van “GOTO” -code-logica.


Antwoord 12

Hoe oud was de auteur?

Ik vraag het omdat ik eens een realtime Fortran-code tegenkwam die dat deed, eind jaren 80. Het blijkt dat dit een heel goede manier is om threads te simuleren op een besturingssysteem dat ze niet heeft. Je plaatst gewoon het hele programma (je planner) in een lus en roept je “thread”-routines één voor één op. De thread-routines zelf zijn lussen die herhalen totdat een van een aantal voorwaarden optreedt (vaak is één een bepaald aantal tijd is verstreken). Het is “coöperatieve multitasking”, in die zin dat het aan de afzonderlijke threads is om af en toe de CPU op te geven, zodat de anderen niet uitgehongerd raken. U kunt de oproepen van het subprogramma in een lus nesten om de prioriteit van de thread te simuleren bands.


Antwoord 13

In aanvulling op de reeds genoemde ‘goto-voorbeelden’, wordt het do … while (0) idioom soms gebruikt in een macrodefinitie om te voorzien in haakjes in de definitie en toch werkt de compiler met het toevoegen van een puntkomma aan het einde van een macrogesprek.

http://groups.google.com/group/comp.soft-sys.ace/browse_thread/thread/52f670f1292f30a4?tvc=2&q=while+(0)


Antwoord 14

Ik ben het eens met de meeste posters over het gebruik als een nauwelijks verhulde goto. Macro’s zijn ook genoemd als een mogelijke motivatie voor het schrijven van code in de stijl.

Ik heb deze constructie ook gezien in gemengde C/C++-omgevingen als een uitzondering voor arme mensen. De “do {} while(false)” met een “break” kan worden gebruikt om naar het einde van het codeblok te springen als er iets in de lus wordt aangetroffen dat normaal gesproken een uitzondering zou rechtvaardigen.

Ik heb deze constructie ook gezien in winkels waar de ideologie van ‘één rendement per functie’ wordt gehandhaafd. Nogmaals, dit is in plaats van een expliciete “goto” – maar de motivatie is om meerdere terugkeerpunten te vermijden, niet om code “over te slaan” en door te gaan met de daadwerkelijke uitvoering binnen die functie.


Antwoord 15

Ik werk met Adobe InDesign SDK en in de InDesign SDK-voorbeelden is bijna elke functie zo geschreven. Het is te wijten aan het feit dat de functie meestal erg lang is. Waar u QueryInterface(…) moet doen om iets uit het toepassingsobjectmodel te halen. Dus meestal wordt elke QueryInterface gevolgd door ifniet goed ging, pauze.


Antwoord 16

Velen hebben de overeenkomst tussen deze constructie en een gotoal aangegeven en een voorkeur voor de goto uitgesproken. Misschien was de achtergrond van deze persoon een omgeving waar goto’s strikt verboden waren door coderingsrichtlijnen?


Antwoord 17

In dergelijke gevallen gebruik ik

switch(true) {
   case condution1:
      ...
      break;
   case condution2:
      ...
      break;
}

Antwoord 18

Dit is grappig. Er zijn waarschijnlijk breuken in de lus, zoals anderen al hebben gezegd. Ik zou het op deze manier hebben gedaan:

while(true)
{
   <main code for function>
   break; // at the end.
}

Other episodes