SORU
29 EYLÜL 2015, Salı


Nasıl global bir değişken ana adı yerine ana işlevi olan bir program.

Program düşünün

#include <iostream>
int main = ( std::cout << "C   is excellent!\n", 195 ); 

G 4.8.1 (mingw64) Windows 7 işletim sistemi üzerinde kullanarak, programı, iyi, matbaa derler çalışır:

C mükemmel!

konsola. main bir işlevi, nasıl bu program fonksiyonu main() olmadan çalıştırabilir mi? yerine global bir değişken görünüyor Bu kod C standardına uygun mu? Programın davranışını iyi tanımlanmış mı? Ayrıca kullanmış-pedantic-errorsseçenek ama program hala derler ve çalıştırır.

CEVAP
29 EYLÜL 2015, Salı


Neler olduğu hakkında soru ve et girmeden önce, önemli bir program kötü oluştuğunu işaret etmek defect report 1886: Language linkage for main() başına:

[...] Genel kapsamında değişken bir ana ilan veya C dili ile bağlantı adı ana tanıtan bir program (herhangi bir ad) hasta oluşturdu. [...]

Çınlama ve gcc en son sürümleri bu bir hata yapar ve programı derleyin (see gcc live example):

error: cannot declare '::main' to be a global variable
int main = ( std::cout << "C   is excellent!\n", 195 ); 
    ^

Neden gcc ve çınlama eski sürümlerinde hiç bir teşhis var mı? Bu kusur raporu bile bir tanı gerektiren bu durum çok yakın zamanda açıkça kötü kuruldu sadece bu kadar geç 2014 yılına kadar önerilen bir çözüm yoktu.

Bundan önce, bu bir ihlal olduğundan tanımsız davranış gibi görünüyorolacaktırBölüm 3.6.1 taslak C standart gereksinimi[temel.başlayın.ana]:

Bir program programın belirlenmiş başlangıç olan küresel bir işlevi ana adlı içerecektir. [...]

Tanımsız davranış tahmin edilemez ve bir tanı gerektirmez. Davranışı yeniden oluşturma ile gördüğümüz tutarsızlık tipik tanımsız davranıştır.

Kodu aslında ne olduğunu ve neden bazı durumlarda sonuçlar üretir? Bakalım neler varmış:

declarator  
|        initializer----------------------------------
|        |                                           |
v        v                                           v
int main = ( std::cout << "C   is excellent!\n", 195 ); 
    ^      ^                                   ^
    |      |                                   |
    |      |                                   comma operator
    |      primary expression
global variable of type int

Bir olan mainintgenel ad olarak ilan edildi ve başlatıldı, değişken statik depolama süresi vardır. Başlatma main aramak için bir girişimde bulundu ama gcc bunu yapıyor gibi görünüyor önce main çağırmadan önce alıp almayacağını uygulama tanımlanır.

Kodu ** 28, sol işlenen atılan bir değer ifade kullanır ve burada sadece std::cout çağırmanın yan etkisi için kullanılır. Virgül operatörünün sonucu bu durumda değişken main atanmış olan prvalue 195 hangi sağ işlenen.

sergej points out cout statik başlatma sırasında çağrılan oluşturulan Kurul gösterir görebiliriz. Daha ilginç bir tartışma noktası olsa da see live godbolt session Bu olurdu:

main:
.zero   4

ve sonraki:

movl    $195, main(%rip)

Muhtemel senaryo programı main geçerli bir kod bekliyor ve some cases will seg-fault için sembol jmps. Eğer bu geçerli bir makine kodu saklamak beklenir durumda değişken main yol açabiliruygulanabilir bir programkod yürütülmesine izin veren bir kesim yer almaktadır varsayarsak. Biz cam this 1984 IOCCC entry just that mu bakın.

C kullanarak bunu yapmak için gcc alabiliriz gibi görünüyor (see it live):

const int main = 195 ;

Bana bu fikri veren ise değişken main yürütülebilir bir konuma sahip comment here Bu Şapka ucunda yer almaktadır çünkü muhtemelen sabit ise-hataları bu seg.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Mark Hyder

    Mark Hyder

    6 EKİM 2011
  • SuicideSheeep

    SuicideSheee

    8 Ocak 2012
  • JeezyVEVO

    JeezyVEVO

    12 Mayıs 2009