Ospecificerat beteende

Ospecificerat beteende ( eng.  ospecificerat beteende ) och implementeringsdefinierat beteende ( eng.  implementeringsdefinierat beteende ) - beteendet hos ett datorprogram , som kan variera på olika plattformar och kompilatorer, eftersom programmeringsspråksspecifikationen erbjuder flera giltiga alternativ för att implementera en viss språkkonstruktion. Till skillnad från odefinierat beteende , anses ett program med ospecificerat beteende inte vara felaktigt ur synvinkeln av överensstämmelse med språkspecifikationen; med ospecificerat beteende begränsar specifikationen vanligtvis de möjliga beteendena, även om den inte reducerar dem till ett enda acceptabelt.

Skillnaden mellan de två är att beteendet är implementeringsdefinierat, dokumenterat och konsekvent över en given processor, miljö, systemversion osv. i nödläge.

Programmeraren bör undvika ospecificerat beteende på platser där det är avgörande för programmets resultat - till exempel om två funktioner anropas i en ospecificerad ordning och de delar felsökningskod, kommer detta att synas i felsökningsloggen , men det kanske inte vara kritisk för resultatet. En programmerare som skriver för en plattform kan bli knuten till sin egen implementering. Och om han skriver ett plattformsoberoende program måste han ta hänsyn till alla rimliga fall av beteende som definieras av implementeringen.

Terminologi

Enligt språkstandarden C99 ,

Originaltext  (engelska)[ visaDölj] 3.4.1 implementeringsdefinierat beteende

ospecificerat beteende där varje implementering dokumenterar hur valet görs

[…]

3.4.3 ospecificerat beteende

användning av ett ospecificerat värde, eller annat beteende där denna internationella standard ger två eller flera möjligheter och inte ställer några ytterligare krav som väljs i något fall — ISO/IEC 9899:201x [1]

Enligt språkstandarden C++ ,

Originaltext  (engelska)[ visaDölj] 1.3.5 implementeringsdefinierat beteende

beteende, för en väl utformad programkonstruktion och korrekt data, som beror på implementeringen och som varje implementering ska dokumentera.

[…]

1.3.13 ospecificerat beteende

beteende, för en välformad programkonstruktion och korrekt data, som beror på implementeringen. Implementeringen krävs inte för att dokumentera vilket beteende som uppstår. [Notera: Vanligtvis är omfattningen av möjliga beteenden avgränsad av denna internationella standard. ]

— ISO/IEC 14882:2003(E)

Exempel

I C och C++ (till skillnad från Java-språket ) är ordningen i vilken funktionsparametrar utvärderas ospecificerad; därför, i programmet nedan, beror ordningen i vilken strängarna "F" och "G" kommer att skrivas ut på kompilatorn.

#include <iostream> int f () { std :: cout << "F" << std :: endl ; retur 3 ; } intg ( ) { std :: cout << "G" << std :: endl ; retur 4 ; } int h ( int i , int j ) { returnera i + j ; } int main () { returnera h ( f (), g ()); }

Det klassiska exemplet på implementeringsdefinierat beteende (ospecificerat beteende som måste dokumenteras av implementeringar) är storleken på datatyper; till exempel kan lång i olika kompilatorer och operativsystem vara 32 eller 64 bitar långa. Ett program som antar att en enda lång alltid passar en pekare kommer inte att fungera korrekt på vissa plattformar (till exempel på Windows x64 ) [2] .

Här är två implementeringar av den snabba inversa kvadratroten : Carmack  - Abrash- implementeringen ( Quake III ) och C++20- implementeringen från engelska Wikipedia:

float Q_rsqrt ( flytnummer ) _ { lång i ; flyta x2 , y ; const float threehalvs = 1,5F ; x2 = antal * 0,5F ; y = nummer ; i = * ( lång * ) & y ; // evil flyttal bitnivå hacking i = 0x5f3759df - ( i >> 1 ); // vad fan? y = * ( flytande * ) & i ; y = y * ( trehalvor - ( x2 * y * y ) ); // 1:a iterationen // y = y * ( threehalvs - ( x2 * y * y ) ) ); // 2:a iterationen, denna kan tas bort returnera y ; } constexpr float Q_rsqrt ( flytnummer ) noexcept _ { static_assert ( std :: numeric_limits < float >:: is_iec559 ); float const y = std :: bit_cast < float > ( 0x5f3759df - ( std :: bit_cast < std :: uint32_t > ( nummer ) >> 1 )); return y * ( 1,5f - ( nummer * 0,5f * y * y )); }

Den första är gjord för Windows och 32-bitars Linux, den andra är mer universell: den ger ett kompileringsfel om maskinen har icke-standardiserade fraktionstyper; tar inte lång tid för att vara 32-bitars.

Se även

Anteckningar

  1. ISO/IEC 9899:201x kommittéutkast - 11 augusti  2008 . Hämtad 1 december 2009. Arkiverad från originalet 11 april 2012.
  2. ↑ storlek lång heltalstyp på olika arkitekturer och operativsystem  . Intel Software Network. Hämtad 1 december 2009. Arkiverad från originalet 11 april 2012.

Länkar