Czy nieskończona pętla, taka jak for (;;);
, niezdefiniowane zachowanie w C? (To is for C++, ale nie wiem o C)Czy (puste) nieskończona pętla niezdefiniowane zachowanie w C?
Odpowiedz
Nie, zachowanie się for (;;)
oświadczenie jest dobrze zdefiniowany w C.
N1570, który jest zasadniczo identyczny z oficjalnym standardem 2011 ISO C, mówi w sekcji 6.8.5 ustęp 6:
instrukcji iteracji którego kontrolowanie ekspresji nie jest stałą wyraz, który nie wykonuje żadnych operacji wejścia/wyjścia, nie ma dostępu do lotnych obiekty, a nie wykonuje żadnej synchronizacji lub atomowy operacje w ciele, kontrolując ekspresję lub (w przypadku oświadczenia dla ) jego wyrażenie -3, może zostać przyjęte przez implementację do zakończenia na .
dwa przypisach:
Pominięta kontroli ekspresji jest zastąpiony przez niezerową wartość stałą, która jest stała ekspresja.
Ma to na celu umożliwienie transformacji kompilatorów, takich jak usuwanie pustych pętli , nawet jeśli nie można potwierdzić zakończenia.
Pierwszy przypis jasno wynika, że for (;;)
jest traktowany tak, jakby miała stałą kontrolę ekspresji.
Punktem reguły jest zezwolenie na optymalizację, gdy kompilator nie może dowieść, że pętla się kończy. Ale jeśli wyrażenia kontrolne są stałe, kompilator może łatwo dowieść, że pętla kończy się lub nie, więc dodatkowe zezwolenie nie jest potrzebne.
* "Punktem reguły jest zezwolenie na optymalizacje, gdy kompilator nie może udowodnić pętla kończy się, ale jeśli wyrażenia sterujące są stałe, kompilator może w sposób trywialny dowieść, że pętla kończy się lub nie kończy. "* Chciałbym się zgodzić, ale dlaczego' while (1); 'nie jest zdefiniowane w C++? Czy to nie to samo rozumowanie? – Mehrdad
@Mehrdad: IMHO powinno, ale standard C++ nie wyklucza stałych wyrażeń sterujących z wersji reguły. –
Tylko po to, aby uchwycić to, co to wszystko oznacza: w C możesz napisać program, w którym logika jest całkowicie zaimplementowana z procedurami obsługi sygnałów i mieć program siedzący w nieskończonej pętli, aby czekać na zdarzenie. To nie brzmi jak bardzo sprytna implementacja czegoś, ale zgadzam się, że język nie powinien tego zabronić. W C++ byłoby to zabronione? –
Uzasadnieniem tej kwestii mający znaczenie do C++ nie ma zastosowania do C. Sekcja 5.1.2.3p6 stany granicach optymalizacji, a jednym z nich jest:
Na zakończenie programu, wszystkie dane zapisywane w plikach musi być identyczny z wynikiem, jaki wytworzyłaby realizacja programu zgodnie z abstrakcyjną semantyką.
Teraz pojawia się pytanie: "Jakie dane byłyby wykonane zgodnie z abstrakcyjną semantyką?". Zakładając, że sygnał przerywa pętlę, program może bardzo dobrze się zakończyć. Jednak semantyka abstrakcyjna nie wytworzyłaby żadnego wyjścia przed podniesieniem tego sygnału. Jeśli coś, kompilator może zoptymalizować odległość.
Aby wyjaśnić, należy rozważyć następujące: program z pustą pętlą, po której następuje 'puts (" Hello ");' jest kompilowany i wykonywany, 'kill' jest używany do wysyłania sygnału do wyjścia programu, a program z wdziękiem robi to, wywołując wyjście z obsługi sygnału. Gdzie jest UB, @Deduplicator? O ile mi wiadomo, jedynym sygnałem UB w sygnałach jest, jeśli program powraca z jednego z sygnałów odpowiadających błędom obliczeniowym. Nie dzieje się to jednak tutaj, ponieważ procedury obsługi sygnału wywołują wyjście, a nie powracają. Proszę wyprostować swoje fakty. – Sebivor
'exit' wykonuje procedury obsługi wyjścia i robi inne rzeczy, które nie są gwarantowane w ogóle. – Deduplicator
@Deduplicator Czy próbujesz mi powiedzieć, że kompilator może nie optymalizować 'puts (" Hello ");' z dala, ponieważ niezdefiniowane zachowanie może być obecne w jednym z procesorów atexit? Konsekwencja niezdefiniowanego zachowania w module obsługi atexit jest ... nieokreślona. Jak to powstrzyma tę optymalizację? – Sebivor
Zobacz także: [Czy kompilatory mogą eliminować nieskończone pętle?] (Http://stackoverflow.com/q/2178115/1708801) –