Comportament nespecificat ( ing. comportament nespecificat ) și comportament definit de implementare ( ing. comportament definit de implementare ) - comportamentul unui program de calculator , care poate varia pe diferite platforme și compilatoare, deoarece specificația limbajului de programare oferă mai multe opțiuni valide pentru implementarea unui anumit construct limbaj. Spre deosebire de comportament nedefinit , un program cu comportament nespecificat nu este considerat eronat din punct de vedere al conformității cu specificația limbajului; cu comportament nespecificat, specificația limitează de obicei comportamentele posibile, deși nu le reduce la unul singur acceptabil.
Diferența dintre cele două este că comportamentul este definit de implementare, documentat și consecvent într-un anumit procesor, mediu, versiune de sistem și așa mai departe, în modul de urgență.
Programatorul ar trebui să evite comportamentul nespecificat în locurile în care este esențial pentru rezultatul programului - de exemplu, dacă două funcții sunt apelate într-o ordine nespecificată și împărtășesc codul de depanare, acesta va fi vizibil în jurnalul de depanare , dar este posibil să nu fie fii critic pentru rezultat. Un programator care scrie pentru o platformă se poate atașa de propria sa implementare. Și dacă scrie un program cross-platform, trebuie să țină cont de toate cazurile rezonabile de comportament definite de implementare.
Conform standardului de limbaj C99 ,
comportament nespecificat în care fiecare implementare documentează modul în care se face alegerea
[…]
3.4.3 comportament nespecificat
utilizarea unei valori nespecificate sau a unui alt comportament în care prezentul standard internațional oferă două sau mai multe posibilități și nu impune alte cerințe pentru care să fie alese în orice caz — ISO/IEC 9899:201x [1]Conform standardului limbajului C++ ,
comportament, pentru un construct de program bine format și date corecte, care depinde de implementare și pe care fiecare implementare trebuie să le documenteze.
[…]
1.3.13 comportament nespecificat
comportament, pentru un construct de program bine format și date corecte, care depinde de implementare. Implementarea nu este necesară pentru a documenta ce comportament are loc. [Notă: de obicei, gama de comportamente posibile este delimitată de acest standard internațional. ]
— ISO/IEC 14882:2003(E)În C și C++ (spre deosebire de limbajul Java ), ordinea în care sunt evaluați parametrii funcției este nespecificată; prin urmare, în programul de mai jos, ordinea în care vor fi tipărite șirurile „F” și „G” depinde de compilator.
#include <iostream> int f () { std :: cout << "F" << std :: endl ; întoarcere 3 ; } intg ( ) { std :: cout << "G" << std :: endl ; întoarcere 4 ; } int h ( int i , int j ) { returnează i + j ; } int main () { returnează h ( f (), g ()); }Exemplul clasic de comportament definit de implementare (comportament nespecificat care trebuie documentat prin implementări) este dimensiunea tipurilor de date; de exemplu, lung în diverse compilatoare și sisteme de operare poate fi de 32 sau 64 de biți. Un program care presupune că un singur lung se va potrivi întotdeauna cu un pointer nu va funcționa corect pe unele platforme (de exemplu, pe Windows x64 ) [2] .
Iată două implementări ale rădăcinii pătrate inverse rapide : implementarea Carmack - Abrash ( Quake III ) și implementarea C++20 din Wikipedia în engleză:
float Q_rsqrt ( număr float ) { i lung ; float x2 , y ; const float threehalfs = 1.5F ; x2 = număr * 0,5F ; y = număr ; i = * ( lung * ) & y ; // evil flating point bit level hacking i = 0x5f3759df - ( i >> 1 ); // ce dracu? y = * ( float * ) & i ; y = y * ( trei jumătăți - ( x2 * y * y ) ); // Prima iterație // y = y * ( trei jumătăți - ( x2 * y * y ) ); // A doua iterație, aceasta poate fi eliminată returnează y ; } constexpr float Q_rsqrt ( număr float ) noexcept { static_assert ( std :: numeric_limits < float >:: is_iec559 ); float const y = std :: bit_cast < float > ( 0x5f3759df - ( std :: bit_cast < std :: uint32_t > ( număr ) >> 1 )); returnează y * ( 1,5f - ( număr * 0,5f * y * y )); }Primul este realizat pentru Windows și Linux pe 32 de biți, al doilea este mai universal: dă o eroare de compilare dacă mașina are tipuri fracționale non-standard; nu necesită mult timp pentru a fi pe 32 de biți.