Ospecificerat beteende
Ospecificerat beteende är beteende som kan variera på olika implementeringar av ett programmeringsspråk . [ förtydligande behövs ] Ett program kan sägas innehålla ospecificerat beteende när dess källkod kan producera en körbar fil som uppvisar olika beteende när den kompileras på en annan kompilator , eller på samma kompilator med olika inställningar, eller faktiskt i olika delar av samma körbar . Även om respektive språkstandard eller specifikationer kan påtvinga en rad möjliga beteenden, beror det exakta beteendet på implementeringen och kanske inte helt avgörs vid granskning av programmets källkod. Ospecificerat beteende kommer ofta inte att visa sig i det resulterande programmets externa beteende, men det kan ibland leda till olika utdata eller resultat, vilket potentiellt kan orsaka portabilitetsproblem .
Definition
För att göra det möjligt för kompilatorer att producera optimal kod för sina respektive målplattformar, kräver inte alltid programmeringsspråksstandarder ett visst specifikt beteende för en given källkodskonstruktion. Att inte explicit definiera det exakta beteendet för alla möjliga program anses inte vara ett fel eller svaghet i språkspecifikationen, och att göra det skulle vara omöjligt. I C- och C++ -språken grupperas sådana icke- portabla konstruktioner i allmänhet i tre kategorier: implementeringsdefinierat, ospecificerat och odefinierat beteende .
Den exakta definitionen av ospecificerat beteende varierar. I C++ definieras det som "beteende, för en välformad programkonstruktion och korrekt data, som beror på implementeringen." C++-standarden noterar också att utbudet av möjliga beteenden vanligtvis tillhandahålls. Till skillnad från implementeringsdefinierat beteende finns det inget krav på att implementeringen ska dokumentera sitt beteende. På liknande sätt definierar C-standarden det som ett beteende för vilket standarden "ger två eller flera möjligheter och inte ställer några ytterligare krav som väljs i något fall". Ospecificerat beteende skiljer sig från odefinierat beteende . Det senare är typiskt ett resultat av en felaktig programkonstruktion eller data, och inga krav ställs på översättning eller exekvering av sådana konstruktioner.
Implementeringsdefinierat beteende
C och C++ skiljer implementeringsdefinierat beteende från ospecificerat beteende. För implementeringsdefinierat beteende måste implementeringen välja ett särskilt beteende och dokumentera det. Ett exempel i C/C++ är storleken på heltalsdatatyper. Valet av beteende måste överensstämma med det dokumenterade beteendet inom en given exekvering av programmet.
Exempel
Ordningsföljd för utvärdering av underuttryck
Många programmeringsspråk anger inte ordningen för utvärdering av underuttrycken för ett komplett uttryck . Denna icke-determinism kan tillåta optimala implementeringar för specifika plattformar, t.ex. för att använda parallellism. Om ett eller flera av underuttrycken har biverkningar kan resultatet av utvärderingen av det fullständiga uttrycket vara annorlunda beroende på ordningen för utvärderingen av underuttrycken. Till exempel givet
a = f ( b ) + g ( b );
, där f
och g
båda modifierar b
, kan resultatet lagrat i a
vara olika beroende på om f(b)
eller g(b)
utvärderas först. I språken C och C++ gäller detta även funktionsargument. Exempel:
#include <iostream> int f () { std :: cout << "I f \n " ; retur 3 ; } int g () { std :: cout << "In g \n " ; retur 4 ; } int summa ( int i , int j ) { return i + j ; } int main () { return summa ( f (), g ()); }
Det resulterande programmet kommer att skriva sina två utdatarader i en ospecificerad ordning. På andra språk, som Java , är ordningen för utvärdering av operander och funktionsargument uttryckligen definierad.