Neler olup bittiğiyle ilgili sorunun temeline geçmeden önce, programın kusur raporu 1886'ya göre kötü biçimlendirildiğini belirtmek önemlidir : main () için dil bağlantısı :
[...] Global kapsamda main değişkenini bildiren veya main adını C dil bağlantısıyla (herhangi bir isim alanında) bildiren bir program bozuk biçimlidir. [...]
En son clang ve gcc sürümleri bunu bir hata yapar ve program derleme yapmaz ( gcc canlı örneğine bakın ):
error: cannot declare '::main' to be a global variable
int main = ( std::cout << "C++ is excellent!\n", 195 );
^
Öyleyse neden eski gcc ve clang sürümlerinde tanılama yoktu? Bu kusur raporu, 2014'ün sonlarına kadar önerilen bir çözüme bile sahip değildi ve bu nedenle, bu vaka, ancak çok yakın zamanda açıkça kötü biçimlendirilmişti, bu da bir teşhis gerektiriyordu.
İhlalde beri bu tanımsız davranış olur gibi Bundan önce, öyle görünüyor -acak bölümünden taslak C gereksinimi ++ standardı 3.6.1
[basic.start.main] :
Bir program, programın belirlenmiş başlangıcı olan main adlı global bir işlevi içerecektir. [...]
Tanımsız davranış tahmin edilemez ve teşhis gerektirmez. Davranışı yeniden oluştururken gördüğümüz tutarsızlık, tipik tanımsız davranıştır.
Öyleyse kod aslında ne yapıyor ve neden bazı durumlarda sonuç üretiyor? Bakalım elimizde ne var:
declarator
| initializer----------------------------------
| | |
v v v
int main = ( std::cout << "C++ is excellent!\n", 195 );
^ ^ ^
| | |
| | comma operator
| primary expression
global variable of type int
Biz main
bir olan int genel ad beyan ve başlatılmakta olan, değişken statik depolama süresi vardır. Bir arama denemesi yapılmadan önce ilklendirmenin gerçekleşip gerçekleşmeyeceği tanımlanmış bir uygulama main
ama gcc bunu aramadan önce yapıyor gibi görünüyor main
.
Kod virgül operatörünü kullanır, soldaki işlenen atılmış bir değer ifadesidir ve burada yalnızca aramanın yan etkisi için kullanılır std::cout
. Virgül operatörünün sonucu, bu durumda 195
değişkene atanan prvalue olan doğru işlenendir main
.
Biz görebilirsiniz dışarı sergej noktaları oluşturulan montaj gösterileri cout
statik başlatma sırasında denir. Tartışma için daha ilginç nokta, canlı godbolt seansına bakın :
main:
.zero 4
ve ardından:
movl $195, main(%rip)
Olası senaryo, programın main
geçerli kodun orada olmasını bekleyen sembole atlaması ve bazı durumlarda segment hatası vermesidir . Bu durumda, geçerli makine kodunu değişkende saklamanın , kod yürütülmesine izin veren bir segmentte bulunduğumuzu varsayarsak, uygulanabilir programamain
yol açmasını bekleriz . Biz görebilirsiniz bu 1984 IOCCC giriş yapar sadece .
Görünüşe göre bunu C ile yapmak için gcc alabiliriz ( canlı görün ):
const int main = 195 ;
Değişken main
çalıştırılabilir bir konumda bulunmadığından dolayı sabit değilse seg-hatası verir, bu yorum bana bu fikri verdi.
Ayrıca , bu sorunun C'ye özgü bir versiyonuna verilen FUZxxl yanıtına da bakın .