Zoeken…


Opmerkingen

Internationale standaard ISO / IEC 9899: 201x programmeertalen - C

Toegang tot een vluchtig object, het wijzigen van een object, het wijzigen van een bestand of het aanroepen van een functie die een van deze bewerkingen uitvoert, zijn allemaal bijwerkingen . Dit zijn wijzigingen in de status van de uitvoeringsomgeving.

De aanwezigheid van een sequentiepunt tussen de evaluatie van uitdrukkingen A en B houdt in dat elke waardeberekening en bijwerking geassocieerd met A wordt bepaald voor elke waardeberekening en bijwerking geassocieerd met B.

Hier is de complete lijst van opeenvolgende punten uit bijlage C van het online pre-publicatieontwerp 2011 van de C-taalstandaard:

Volgorde punten

1 Hieronder volgen de opeenvolgende punten die worden beschreven in 5.1.2.3:

  • Tussen de evaluaties van de functie-aanwijzer en werkelijke argumenten in een functie-aanroep en de werkelijke aanroep. (6.5.2.2).
  • Tussen de evaluaties van de eerste en tweede operanden van de volgende operatoren: logische AND && (6.5.13); logisch OF || (6.5.14); komma , (6.5.17).
  • Tussen de evaluaties van de eerste operand van de voorwaardelijke ? : operator en welke van de tweede en derde operanden ook wordt geëvalueerd (6.5.15).
  • Het einde van een volledige aangever: aangever (6.7.6);
  • Tussen de evaluatie van een volledige uitdrukking en de volgende volledige uitdrukking die moet worden geëvalueerd. De volgende zijn volledige uitdrukkingen: een initialisatie die geen deel uitmaakt van een letterlijke verbinding (6.7.9); de uitdrukking in een uitdrukkingsverklaring (6.8.3); de controlerende uitdrukking van een selectieopdracht ( if of switch ) (6.8.4); de controlerende uitdrukking van een while of do instructie (6.8.5); elk van de (optionele) uitdrukkingen van een for instructie (6.8.5.3); de (optionele) uitdrukking in een return (6.8.6.4).
  • Onmiddellijk voordat een bibliotheekfunctie terugkeert (7.1.4).
  • Na de acties die zijn gekoppeld aan elke geformatteerde invoer / uitvoer-functieomzettingsspecificatie (7.21.6, 7.29.2).
  • Direct voor en onmiddellijk na elke aanroep van een vergelijkingsfunctie, en ook tussen elke aanroep van een vergelijkingsfunctie en elke beweging van de objecten die als argumenten aan die aanroep werden doorgegeven (7.22.5).

Reeksen uitdrukkingen

De volgende uitdrukkingen worden op volgorde geplaatst :

a && b
a || b
a , b
a ? b : c
for ( a ; b ; c ) { ... }

In alle gevallen wordt de uitdrukking a volledig geëvalueerd en worden alle bijwerkingen toegepast voordat b of c worden geëvalueerd. In het vierde geval wordt slechts één van b of c geëvalueerd. In het laatste geval wordt b volledig geëvalueerd en worden alle bijwerkingen toegepast voordat c wordt geëvalueerd.

In alle gevallen wordt de evaluatie van expressie a gesequenced vóór de evaluaties van b of c (alternatief worden de evaluaties van b en c gesequenced na de evaluatie van a ).

Dus uitdrukkingen zoals

x++ && x++
x++ ? x++ : y++ 
(x = f()) && x != 0
for ( x = 0; x < 10; x++ ) { ... }
y = (x++, x++);

goed gedefinieerd gedrag hebben.

Onvolgorde uitdrukkingen

C11

De volgende uitdrukkingen hebben geen opeenvolging :

a + b;
a - b;
a * b;
a / b;
a % b;
a & b;
a | b;

In de bovenstaande voorbeelden kan de uitdrukking a worden geëvalueerd voor of na de uitdrukking b , b kan worden geëvalueerd vóór a , of ze kunnen zelfs worden gemengd als ze overeenkomen met verschillende instructies.

Een vergelijkbare regel geldt voor functieaanroepen:

f(a, b);

Hier niet alleen a en b zijn unsequenced (dwz , operator in een functieaanroep produceert geen sequentie punt), maar ook f , de uitdrukking dat de functie die wordt genoemd bepalend.

Bijwerkingen kunnen onmiddellijk na de evaluatie worden toegepast of tot een later tijdstip worden uitgesteld.

Uitdrukkingen zoals

x++ & x++;
f(x++, x++); /* the ',' in a function call is *not* the same as the comma operator */
x++ * x++;
a[i] = i++;

of

x++ & x;
f(x++, x);
x++ * x;
a[i++] = i;

levert ongedefinieerd gedrag op omdat

  • een wijziging van een object en elke andere toegang daartoe moet worden gesequenced
  • de volgorde van evaluatie en de volgorde waarin bijwerkingen 1 worden toegepast, is niet gespecificeerd.

1 Eventuele wijzigingen in de status van de uitvoeringsomgeving.

Onbepaalde opeenvolgingen van uitdrukkingen

Functie-aanroepen als f(a) impliceren altijd een reekspunt tussen de evaluatie van de argumenten en de aanduiding (hier f en a ) en de daadwerkelijke aanroep. Als twee van dergelijke aanroepen niet worden gerangschikt, worden de twee functie-aanroepen onbepaald op volgorde gezet, d.w.z. de ene wordt vóór de andere uitgevoerd en de volgorde is niet gespecificeerd.

unsigned counter = 0;

unsingned account(void) {
   return counter++;
}

int main(void) {
   printf("the order is %u %u\n", account(), account());
}

Deze impliciete tweevoudige wijziging van counter tijdens de evaluatie van de printf argumenten is geldig, we weten gewoon niet welke van de aanroepen eerst komt. Omdat de bestelling niet is gespecificeerd, kan deze variëren en kan er niet op worden vertrouwd. Dus de afdruk kan zijn:

de bestelling is 0 1

of

de bestelling is 1 0

De analoge verklaring als hierboven zonder tussentijdse functieaanroep

   printf("the order is %u %u\n", counter++, counter++); // undefined behavior

heeft ongedefinieerd gedrag omdat er geen volgordepunt is tussen de twee modificaties van de counter .



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow