Sök…


Anmärkningar

International Standard ISO / IEC 9899: 201x Programmeringsspråk - C

Att komma åt ett flyktigt objekt, ändra ett objekt, ändra en fil eller ringa en funktion som gör någon av dessa operationer är alla biverkningar , vilket är förändringar i exekveringsmiljöns tillstånd.

Närvaron av en sekvenspunkt mellan utvärderingen av uttryck A och B innebär att varje värderäkning och bieffekt associerad med A sekvenseras före varje värderäkning och bieffekt associerad med B.

Här är den fullständiga listan med sekvenspunkter från bilaga C till onlineutkastet för 2011 för publicering av C-språkstandarden

Sekvenspoäng

1 Följande är de sekvenspunkter som beskrivs i 5.1.2.3:

  • Mellan utvärderingarna av funktionsbetecknaren och faktiska argument i ett funktionssamtal och det faktiska samtalet. (6.5.2.2).
  • Mellan utvärderingarna av de första och andra operandema hos följande operatörer: logisk AND && (6.5.13); logisk ELLER || (6.5.14); komma , (6.5.17).
  • Mellan utvärderingarna av den första operand av den villkorade ? : operatör och vilken som helst av den andra och tredje operand utvärderas (6.5.15).
  • Slutet på en fullständig deklarator: deklaratorer (6.7.6);
  • Mellan utvärderingen av ett fullt uttryck och nästa fullständiga uttryck som ska utvärderas. Följande är fullständiga uttryck: en initialisator som inte är en del av en sammansatt bokstavlig (6.7.9); uttrycket i ett uttrycksuttalande (6.8.3); det styrande uttrycket för en markeringssats ( if eller switch ) (6.8.4); den styrande uttryck av en while eller do uttalande (6.8.5); vart och ett av (valfritt) uttryck för en for uttalande (6.8.5.3); (tillval) uttryck i en return uttalande (6.8.6.4).
  • Omedelbart innan en biblioteksfunktion återgår (7.1.4).
  • Efter de åtgärder som är associerade med varje formaterad konverteringsspecifikation för input / output-funktion (7.21.6, 7.29.2).
  • Omedelbart före och omedelbart efter varje samtal till en jämförelsefunktion, och även mellan alla samtal till en jämförelsefunktion och varje rörelse av objekten som har skickats som argument till det samtalet (7.22.5).

Sekvenserade uttryck

Följande uttryck sekvenseras :

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

I alla fall utvärderas uttrycket a fullständigt och alla biverkningar tillämpas innan antingen b eller c utvärderas. I det fjärde fallet kommer endast en av b eller c att utvärderas. I det sista fallet utvärderas b fullständigt och alla biverkningar tillämpas innan c utvärderas.

I alla fall sekvenseras utvärderingen av uttrycket a innan utvärderingarna av b eller c (omväxlande sekvenseras utvärderingarna av b och c efter utvärderingen av a ).

Således uttryck som

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

har väl definierat beteende.

Senare uttryck

C11

Följande uttryck följs inte :

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

I ovanstående exempel kan uttrycket a utvärderas före eller efter uttrycket b , b kan utvärderas före a , eller de kan till och med blandas om de motsvarar flera instruktioner.

En liknande regel gäller för funktionssamtal:

f(a, b);

Här inte bara a och b är unsequenced (dvs. , inte operatören i ett funktionsanrop inte producera en sekvens punkt) men också f , uttrycket som bestämmer den funktion som ska anropas.

Biverkningar kan appliceras omedelbart efter utvärdering eller uppskjutas tills en senare punkt.

Uttryck som

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

eller

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

kommer att ge odefinierat beteende eftersom

  • en modifiering av ett objekt och annan åtkomst till det måste sekvenseras
  • utvärderingsordningen och i vilken ordning biverkningar 1 tillämpas anges inte.

1 Eventuella förändringar i exekveringsmiljöns tillstånd.

Obestämd sekvenserade uttryck

Funktionssamtal som f(a) innebär alltid en sekvenspunkt mellan utvärderingen av argumenten och betecknaren (här f och a ) och det faktiska samtalet. Om två sådana samtal följs inte sekvenseras de två funktionssamtalen obestämd, det vill säga ett utförs före det andra och ordningen är ospecificerad.

unsigned counter = 0;

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

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

Denna implicita tvåfaldiga modifiering av counter under utvärderingen av printf argumenten är giltig, vi vet bara inte vilket av samtal som kommer först. Eftersom beställningen är ospecificerad kan den variera och kan inte bero på den. Så utskriften kan vara:

ordningen är 0 1

eller

ordningen är 1 0

Det analoga uttalandet till ovanstående utan mellanfunktionssamtal

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

har odefinierat beteende eftersom det inte finns någon sekvenspunkt mellan de två modifikationerna av counter .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow