C standardının "davranış" ve "tanımlanmamış davranış" terimlerini nasıl tanımladığına bakalım.
Referanslar , ISO C 2011 standardının N1570 taslağına; Yayınlanan üç ISO C standardından (1990, 1999 ve 2011) herhangi bir ilgili farkın farkında değilim.
Bölüm 3.4:
davranış
dış görünüş veya eylem
Tamam, bu biraz belirsiz, ancak belirli bir ifadenin "görünüşü" olmadığını ve gerçekten yürütülmedikçe kesinlikle "eylem" olmadığını iddia ediyorum.
Bölüm 3.4.3:
Taşınabilir olmayan veya hatalı bir program yapısının veya hatalı verilerin kullanılması durumunda, bu Uluslararası Standardın herhangi bir gereklilik getirmediği, tanımlanmamış davranış davranışı
Böyle bir yapının " kullanımı üzerine " yazıyor . "Kullanım" kelimesi standart tarafından tanımlanmadığından, ortak İngilizce anlamına geri dönüyoruz. Hiç çalıştırılmazsa bir yapı "kullanılmaz".
Bu tanımın altında bir not var:
Not - Olası tanımlanmamış davranış, durumu tamamen öngörülemeyen sonuçlarla göz ardı etmekten, çevrenin özelliği olan belgelenmiş bir şekilde (bir teşhis mesajı yayınlayarak veya vermeden) çeviri veya program yürütme sırasında davranmaya, bir çeviriyi veya yürütmeyi sonlandırmaya ( bir teşhis mesajının verilmesi).
Dolayısıyla, bir derleyicinin davranışı tanımsız ise derleme zamanında programınızı reddetmesine izin verilir . Ama bu benim yorumlanması o kadar yapabilmesidir sadece o programın her yürütme tanımsız davranış karşılaşacak ispat eğer. Sanırım bu şu anlama geliyor:
if (rand() % 2 == 0) {
i = i / 0;
}
kesinlikle hangi edebilirsiniz tanımsız davranışa sahip, derleme zamanında reddedilemez.
Pratik bir mesele olarak, programların tanımsız davranışları harekete geçirmeye karşı koruma sağlamak için çalışma zamanı testleri gerçekleştirebilmesi gerekir ve standardın buna izin vermesi gerekir.
Örneğiniz şuydu:
if (0) {
i = 1/0;
}
0 ile bölmeyi asla gerçekleştirmez. Çok yaygın bir deyim:
int x, y;
if (y != 0) {
x = x / y;
}
Bölüm kesinlikle tanımlanmamış davranışa sahiptir y == 0
, ancak hiçbir zaman yürütülmez y == 0
. Davranış iyi tanımlanmıştır ve örneğinizin iyi tanımlanmasıyla aynı nedenden ötürü: çünkü potansiyel tanımlanmamış davranış aslında asla gerçekleşemez.
(Tabii INT_MIN < -INT_MAX && x == INT_MIN && y == -1
(evet, tamsayı bölme aşabilir), ancak bu ayrı bir konudur.
Bir yorumda (silindiğinden beri), birisi derleyicinin sabit ifadeleri derleme zamanında değerlendirebileceğine işaret etti. Hangisi doğru, ancak bu durumda alakalı değil, çünkü bağlamında
i = 1/0;
1/0
sabit bir ifade değildir .
Bir sabit ekspresyon azaltan bir sözdizimsel bir kategoridir koşullu ekspresyonu (ki hariç atamaları ve virgül ifadeler). Üretim sabiti ifadesi , dilbilgisinde yalnızca durum etiketleri gibi sabit bir ifade gerektiren bağlamlarda görünür . Yani yazarsan:
switch (...) {
case 1/0:
...
}
o zaman 1/0
sabit bir ifadedir - ve 6.6p4'teki kısıtlamayı ihlal eden bir ifade: "Her bir sabit ifade, türü için gösterilebilir değerler aralığında olan bir sabit olarak değerlendirilmelidir.", bu nedenle bir teşhis gereklidir. Ancak bir atamanın sağ tarafı bir sabit ifade gerektirmez , yalnızca bir koşullu ifade gerektirir , bu nedenle sabit ifadeler üzerindeki kısıtlamalar uygulanmaz. Derleyici ama bağlamında, yürütme sırasında değerlendirilir (ya da sanki davranışı aynı olduğu takdirde, derleme zamanında yapabilen herhangi bir ifade değerlendirebilir if (0)
, değil, yürütme sırasında değerlendirilir ().
(Tam olarak benzer bir görünüm olduğu bir şey sabit ekspresyon mutlaka değil, sabit bir ifade içinde, gibi, x + y * z
sekans x + y
bir değil, katkı maddesi-sentezleme için göründüğü bağlam).
Bu, N1570 bölüm 6.6'daki alıntı yapacağım dipnot anlamına gelir:
Bu nedenle, aşağıdaki ilklendirmede
static int i = 2 || 1 / 0;
ifade, değeri bir olan geçerli bir tamsayı sabit ifadesidir.
aslında bu soruyla alakalı değil.
Son olarak, yürütme sırasında olanlarla ilgili olmayan tanımlanmamış davranışlara neden olmak için tanımlanan birkaç şey vardır. C standardının Ek J, bölüm 2'si (yine N1570 taslağına bakın ), standardın geri kalanından toplanan tanımlanmamış davranışa neden olan şeyleri listeler. Bazı örnekler (bunun kapsamlı bir liste olduğunu iddia etmiyorum):
- Boş olmayan bir kaynak dosyası, hemen önünde ters eğik çizgi karakteri bulunmayan veya kısmi bir ön işleme belirteci veya yorumla biten yeni bir satır karakteriyle bitmez
- Belirteç birleştirme, evrensel bir karakter adının sözdizimiyle eşleşen bir karakter dizisi üretir
- Bir tanımlayıcı, bir karakter sabiti, bir dize değişmezi, bir başlık adı, bir açıklama veya hiçbir zaman bir jetona dönüştürülmeyen bir ön işleme belirteci dışında, bir kaynak dosyada temel kaynak karakter kümesinde olmayan bir karakterle karşılaşılır.
- Bir tanımlayıcı, açıklama, dize değişmezi, karakter sabiti veya başlık adı geçersiz bir çok baytlı karakter içeriyor veya ilk vardiya durumunda başlamıyor ve bitmiyor
- Aynı tanımlayıcı, aynı çeviri biriminde hem dahili hem de harici bağlantıya sahiptir
Bunlar belirli vakalar derleyici şeylerdir olabilir algılar. Komite tüm uygulamalara aynı davranışı empoze etmek istemedi ya da empoze edemediğinden davranışlarının tanımsız olduğunu düşünüyorum ve bir dizi izin verilen davranışı tanımlamak çabaya değmezdi. "Asla çalıştırılmayacak kod" kategorisine girmiyorlar, ama burada tamlık için onlardan bahsediyorum.