Il compilatore funziona sotto la regola as-if che consente qualsiasi e tutte le trasformazioni di codice che don ' t modificare il comportamento osservabile del programma.
[C ++ 14: 1.5 / 8]
The least requirements on a conforming implementation are:
- Access to volatile objects are evaluated strictly according to the rules of the abstract machine.
- At program termination, all data written into files shall be identical to one of the possible results that execution of the program according to the abstract semantics would have produced.
- The input and output dynamics of interactive devices shall take place in such a fashion that prompting output is actually delivered before a program waits for input. What constitutes an interactive device is implementation-defined.
These collectively are referred to as the observable behavior of the program.
[C11 5.1.2.3.6 Esecuzione del programma] ha una dicitura simile:
The least requirements on a conforming implementation are:
- Accesses to volatile objects are evaluated strictly according to the rules of the abstract machine.
- At program termination, all data written into files shall be identical to the result that execution of the program according to the abstract semantics would have produced.
- The input and output dynamics of interactive devices shall take place as specified in 7.21.3. The intent of these requirements is that unbuffered or line-buffered output appear as soon as possible, to ensure that prompting messages actually appear prior to a program waiting for input.
This is the observable behavior of the program.
Un ritardo non è considerato un comportamento osservabile e il primo esempio può essere "ottimizzato" per un programma vuoto.
Si noti che, per consentire trasformazioni del compilatore come la rimozione di loop vuoti (anche quando la terminazione non può essere dimostrata), gli standard C ++ 14 dicono:
[C ++ 14: 1.10 / 24]
The implementation may assume that any thread will eventually do one of the following:
- terminate,
- make a call to a library I/O function,
- access or modify a volatile object, or
- perform a synchronization operation or an atomic operation.
[ Note: This is intended to allow compiler transformations such as removal of empty loops, even when termination cannot be proven. —end note ]
(vedi anche C / C ++ offre alcuna garanzia sui tempi di esecuzione minimi? )
Il secondo esempio è più difficile per il compilatore perché di solito non è in grado di analizzare il codice di una libreria esterna per determinare se esegue / non esegue I / O o accesso volatile. Tuttavia, il codice di libreria di terze parti collegato in modo statico può essere soggetto a ottimizzazione del tempo di collegamento così
un'organizzazione multi-file non è una barriera insormontabile.
Il terzo esempio non introduce nulla di nuovo:
- la voce del vettore di interruzione viene inizializzata all'avvio del programma
- che implica l'assunzione dell'indirizzo della funzione del gestore ed è sufficiente per proteggere
hardware_timer_isr
dall'ottimizzazione
-
ma la variabile time
non viene designata manualmente come variabile che può essere modificata dai gestori di interrupt, quindi le istruzioni:
timer_start(LARGE_NUM);
while(timer_busy());
non hanno un comportamento osservabile e possono essere ottimizzati (vedi Perché il compilatore non ottimizza il codice di interruzione di accesso? per ulteriori dettagli).
Se hai bisogno di un ritardo puoi utilizzare std::sleep_for
o std::sleep_until
.
ULTERIORI NOTE
What if I deliberately put a while(1);
or a similarly obfuscated infinite loop to intentionally halt the program? According to C++14 1.10/24 above, even though the termination can not be proven, the loop itself does not change the observable behavior of the program and thus can be legally removed, right?
Il motivo della nota ( "è inteso a consentire trasformazioni del compilatore come la rimozione di loop vuoti, anche quando la risoluzione non può essere dimostrata" ) è
non c'è modo di rilevare universalmente loop infiniti e l'incapacità di provare la terminazione ostacola i compilatori che potrebbero altrimenti fare trasformazioni utili (c'è un buon esempio in N1528: Perché comportamento indefinito per loop infiniti? ).
Per il linguaggio C ++ la situazione è descritta in:
Per il linguaggio C C11 fornisce un'eccezione per il controllo di espressioni che sono espressioni costanti .