Neden auto a = 1; C'de derlemek mi?


125

Kod:

int main(void)
{
    auto a=1;
    return 0;
}

dosya .c uzantısına sahip olduğunda, MS Visual Studio 2012 derleyicisi tarafından hatasız olarak derlenir. Her zaman .c uzantısını kullandığınızda, derlemenin C ++ 'ya değil C sözdizimine göre olması gerektiğini düşünmüşümdür. Dahası, bildiğim kadarıyla bir tür olmadan otomatik'e yalnızca C ++ ' da izin verilir , burada C ++ 11'den beri, bu, türün başlatıcıdan çıkarıldığı anlamına gelir.

Bu, derleyicimin C'ye sadık kalmadığı anlamına mı geliyor yoksa kod C dilinde gerçekten doğru mu?


8
Ya C ++ kipiyle (mümkün) derlersiniz ya da MS hala son milenyumda takılı kalır. Örtük int1999'da C standardından kaldırıldı.
Jens Gustedt

16
@JensGustedt MSVC ++ yalnızca C89'u (ve C99'un birkaç özelliğini) destekler. Daha çok bir C ++ derleyicisidir.
ntoskrnl

3
@Brandin: / Wall seçeneğiyle, bir tür belirticisinin eksik olduğunu ve varsayılan int'in artık C'de desteklenmediğini söyleyerek C4431'i uyarır (Jens'in yorumuna bakın). Belli ki bu derleyici desteklediği için biraz çelişki var ...
lee77

4
@JensGustedt Bu ölçüye göre, 2012'de yayınlanan GCC 4.7 (ve daha sonraki sürümlerde de şüpheleniyorum - elimde bunlar yok) "son milenyumda sıkışmış". Herhangi bir bayrak verilmediğinde, OP'nin kodunu herhangi bir bildirimde bulunmaksızın derler.

3
@delnan, en azından OP'nin uyarı seviyelerini açtığını tahmin ediyordum. Açıkçası yanılmışım. Ve bir bakıma bu doğrudur, gcc de hala varsayılan olarak C99'a (veya bir varyantına) sahip olmadıkları için orada kalmıştır. clang, bayraklar olmadan bile yapı hakkında uyarır.
Jens Gustedt

Yanıtlar:


240

auto"yerel kapsam" anlamına gelen eski bir C anahtar kelimesidir. auto aile aynıdır auto int ave yerel kapsam, bir işlevin içinde bildirilen bir değişken için varsayılan olduğundan, int abu örnekteki ile aynıdır .

Bu anahtar kelime aslında C'nin öncülü B'den geriye kalmıştır, burada hiçbir temel tür yoktur: her şey int, işaretçi int, dizi int. (*) Bildirimler ya ya autoda extrn[sic] olurdu . C, intvarsayılan bir kural olarak "her şey " i miras almıştır , bu nedenle

auto a;
extern b;
static c;

ISO C bundan kurtuldu, ancak birçok derleyici hala geriye dönük uyumluluk için bunu kabul ediyor. Tanıdık gelmiyorsa, o zaman ilgili bir kuralın iş başında olduğunu anlamalısınız.

unsigned d;  // actually unsigned int

modern kodda hala yaygındır.

C ++ 11, tür çıkarımı için herhangi bir C ++ programcısının orijinal anlamıyla kullandığı anahtar kelimeyi yeniden kullandı. Bu çoğunlukla güvenlidir çünkü intC'deki "her şeydir " kuralı C ++ 98'de zaten kaldırılmıştı; kırılan tek şey, auto T azaten kimsenin kullanmadığıdır. ( Stroustrup , dilin tarihi hakkındaki makalelerinde bir yerlerde bu konuda yorum yapıyor, ancak şu anda tam referansı bulamıyorum.)

(*) B'de dize kullanımı ilginçti: dizileri kullanır intve her üyede birden çok karakter paketlerdiniz. B aslında farklı sözdizimine sahip BCPL idi .


7
Hayır, bu 1999'dan beri yasal C değildir. Hiçbir düzgün modern C derleyicisi buna izin vermez.
Jens Gustedt

18
@JensGustedt VS, modern bir C derleyicisi sağladığını iddia etmez. Görünüşe göre, C derleyicisindeki çalışmalar yıllar önce durdu; sadece insanların eski kodu derlemeye devam edebilmesi için sağlarlar. (Ve tabii ki, herhangi bir düzgün modern C derleyicisinin eski kodu destekleme seçenekleri olacaktır. K&R C için bir seçenek de dahil)
James Kanze

23
@JensGustedt: Emin misin? GCC ve Clang, her ikisi de C99 modunda uyarıyor, ancak ile dışında bir hata olarak görmüyorlar -Werror.
Fred Foo

2
@larsman, evet, 6.7.2'de bunun için açık bir kısıtlama var: Her beyanda en az bir tip
tanımlayıcı

40
@JensGustedt - re Hayır, bu 1999'dan beri yasal C değildir. Hiçbir düzgün modern C derleyicisi buna izin vermez. İlk ifade doğrudur; 1999'dan beri yasa dışıdır. IMHO, ikinci ifade yanlıştır. Herhangi bir düzgün modern C derleyicisi buna izin vermelidir. İzin vermedikleri takdirde yeniden yazılması gereken tüm eski koda bakın. Bu yoruma genişleyen bir cevap yazdım.
David Hammen

35

Bu hem bir cevap hem de Hayır'a genişletilmiş bir yorumdur , bu 1999'dan beri yasal C değildir. Hiçbir düzgün modern C derleyicisi buna izin vermez.

Evet, auto a=1;C1999'da (ve ayrıca C2011'de) yasa dışıdır. Bunun artık yasadışı olması, modern bir C derleyicisinin bu tür yapıları içeren kodu reddetmesi gerektiği anlamına gelmez. Tam tersini, iyi bir modern C derleyicisinin buna hala izin vermesi gerektiğini iddia ediyorum.

Hem clang hem de gcc, sorudaki örnek kodu standardın 1999 veya 2011 sürümlerine göre derlerken bunu yapar. Her iki derleyici de bir tanılama yayınlar ve sonra sanki sakıncalı ifade öyleymiş gibi devam eder auto int a=1;.

Bence iyi bir derleyicinin yapması gereken bu. Bir tanılama yayınlayarak, clang ve gcc standartla tam uyumludur. Standart, bir derleyicinin yasadışı kodu reddetmesi gerektiğini söylemez. Standart sadece, bir çeviri birimi herhangi bir sözdizimi kuralı veya kısıtlamasının (5.1.1.3) ihlalini içeriyorsa, uyumlu bir uygulamanın en az bir teşhis mesajı üretmesi gerektiğini söyler.

Yasadışı yapılar içeren kod verildiğinde, herhangi bir düzgün derleyici, derleyicinin koddaki bir sonraki hatayı bulabilmesi için yasa dışı kodu anlamaya çalışacaktır. İlk hatada duran bir derleyici çok iyi bir derleyici değildir. Bir anlam ifade etmenin bir yolu var, auto a=1"örtük int" kuralını uygulamak. Bu kural, derleyiciyi , derleyici C90 veya K&R modunda kullanıldığı zamanki auto a=1gibi yorumlamaya zorlar auto int a=1.

Çoğu derleyici tipik olarak yasadışı sözdizimi içeren kodu reddeder (reddetme: bir nesne dosyası veya bir yürütülebilir dosya oluşturmayı reddetme). Bu, derleyici yazarlarının derleme başarısızlığının en iyi seçenek olmadığına karar verdiği bir durumdur. Yapılacak en iyi şey, bir teşhis yapmak, kodu düzeltmek ve devam etmektir. Gibi yapılarla dolu çok fazla eski kod var register a=1;. Derleyici bu kodu C99 veya C11 modunda derleyebilmelidir (tabii ki bir tanılama ile).


1
@larsmans - Nereden geldiğinizi görebiliyorum. Bir -ffs-please-stop-allowing-constructs-from-some-previous-millenniumderleyici seçeneği veya kısaca bir -fstrict-complianceseçenek istiyorsunuz. Derleyici değişikliklerine söylenmek: "Ben o eski K & F derlemeye Kruft hiç ummadığım -std = c11 kullanıldığında ise aslında, ben istediğim değil derlemek!"
David Hammen

1
Aslında hayır, çevirmek istiyorum üzerinde derleme için en kötü cruft almak için bir bayrak. Ancak -std=c99daha katı olmak doğru yönde atılmış bir adım olur :)
Fred Foo

1
Eğer kullanırsanız gcc -g -O3 -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror(SO'daki sorulardan gelen kodlarda bile rutin olarak kullandığım şey budur), o zaman istediğiniz şeye oldukça yaklaşırsınız. GCC'nin en azından -std=c99ve tercihen varsayılan yapmasını istiyorum -std=c11(veya, -std=gnu11muhtemelen bunu yaparlar), ancak o zamana kadar… Bu seçenekleri değiştirebilirsiniz; -pedantic, -Wshadow, -Wold-style-declarationVe bazı diğerleri yararlı olabilir, ancak bu seçeneklerin ayarlanmış yolvermeye bir iyidir.
Jonathan Leffler

3
@DavidHammen: Ne döngüsel karmaşıklık, proje yöneticileri ne de şirket politikaları dilin unsurlarıdır.
Jerry B

3
GCC'de istediğiniz davranışı elde etmek için bayrak-pedantic-errors
τεκ

29

auto2011 Standardı içinde Cve C++öncesinde bir anlama sahiptir . Bir değişkenin otomatik yaşam süresine, yani kapsam tarafından belirlenen yaşam süresine sahip olduğu anlamına gelir . Bu, statickapsamı ne olursa olsun, bir değişkenin "sonsuza kadar" sürdüğü yaşam süresinin tersidir. autovarsayılan ömürdür ve neredeyse hiçbir zaman açıkça ifade edilmez. Bu yüzden anlamını değiştirmek güvenliydi C++.

Şimdi C, 99 Standardından önce, bir değişkenin türünü belirtmezseniz, varsayılan olur int.

Öyleyse auto a = 1;sizinle birlikte bir intdeğişken bildiriyorsunuz (ve tanımlıyorsunuz) , yaşam süresi kapsam tarafından belirlenir.

("ömür" daha doğru bir şekilde "depolama süresi" olarak adlandırılır, ancak bunun belki de daha az açık olduğunu düşünüyorum).


Tamam, yani aslında otomatik a = 1'e C'de izin verilir ve otomatik depolama süresi olan bir int değişkeni anlamına gelir.
lee77

1
Düzgün bir şekilde, "depolama süresi", "otomatik", "statik", "dinamik", "iş parçacığı" değerler listesinden birini alır. "Ömür", nesnenin gerçek yaşam süresidir. Dolayısıyla değişkenin depolama süresi "otomatik" ve yaşam süresi " mainişlev kapsamının süresi " vardır.
Steve Jessop

@Steve evet, bunu ima etmek istemedim autove staticsadece iki olasılık. Cevabımı soruyu soran kişiyi hedef alan bir şekilde yazmaya çalışıyordum, bu soruyu soran kişi için oldukça yeni görünüyordu C++(ve C), bu yüzden ayrıntıları biraz parlattım. Belki bu kötü bir fikirdi; er ya da geç kapsanmaları gerekir.
BoBTFish

1
@BoBTFish: oh, bundan şikayetçi değildim. Sadece bir süre olan "yaşam süresi" ile "depolama süresi kategorisi" olarak adlandırılabilecek "depolama süresi" arasındaki anlamsal farkı genişletmek istedim.
Steve Jessop

Bu örtük intşeyler 1999'dan beri C'den kaldırıldı.
Jens Gustedt

8

C ve C ++ ' autonın tarihi lehçelerinde a, otomatik depolamaya sahip bir anahtar kelime anlamı vardır. Yalnızca varsayılan olarak otomatik olan yerel değişkenlere uygulanabildiğinden, kimse kullanmaz; bu yüzden C ++ artık anahtar kelimeyi yeniden tasarladı.

Tarihsel olarak C, tür belirticisi olmayan değişken bildirimlerine izin vermiştir; tür varsayılan olarak int. Yani bu beyan eşdeğerdir

int a=1;

Sanırım bu, modern C'de kullanımdan kaldırıldı (ve muhtemelen yasak); ancak bazı popüler derleyiciler varsayılan olarak C90'ı kullanır (ki buna izin verir) ve sinir bozucu bir şekilde, yalnızca özellikle sorarsanız uyarıları etkinleştirir. İle C99 belirterek ya GCC ile Derleme ve -std=c99ya ile uyarı etkinleştirerek -Wallveya -Wimplicit-intbir uyarı verir:

warning: type defaults to int in declaration of a

4
1999'dan beri C'de gerçekten yasak.
Jens Gustedt

5

C'de, C ++ 11'de autoaynı şey registerolduğu anlamına gelir: bir değişkenin otomatik depolama süresine sahip olduğu anlamına gelir.

Ve C99'dan önceki C'de (ve Microsoft'un derleyicisi, C99'u veya C11'i desteklemez, ancak bazı kısımlarını destekleyebilir), tür, varsayılan olarak kullanılacağı birçok durumda ihmal edilebilir int.

Türü başlatıcıdan hiç almaz. Uyumlu olan bir başlatıcı seçtiniz.


1
Register anahtar sözcüğü C ++ 11'de kullanımdan kaldırılmadı mı?
iğrenç

@sordid Evet, öyle. C ++ 11'den önce autove registeraynı anlama sahipti (Daha önce register-kalifiye bir değişkenin adresini alma konusunda kısıtlamalar olduğunu, ancak bunun C ++ için yanlış olduğunu yorumlamıştım). registerkullanımdan kaldırılmışken şimdilik eski anlamını koruyor.

5
@JensGustedt: Cevap öyle olduklarını söylemiyor. autoC'nin registerC ++ ile aynı anlama geldiğini söyler (her ikisi de otomatik depolama süresi anlamına gelir ve başka hiçbir şey anlamına gelmez).
Mike Seymour

3

Görsel stüdyo derleme türü adresinde mevcuttur right click on file -> Properties -> C/C++ -> Advanced -> Compile As. C force seçeneği olarak derlendiğinden emin olmak için, /TCsonra bu durumda larsmans'ın söylediği şeydir (eski C autoanahtar kelimesi). Siz bilmeden C ++ olarak derlenebilir.


3

Bir depolama sınıfı, bir C Programı içindeki değişkenlerin ve / veya işlevlerin kapsamını (görünürlük) ve yaşam süresini tanımlar.

Bir C Programında kullanılabilecek aşağıdaki depolama sınıfları vardır

auto
register
static
extern

auto tüm yerel değişkenler için varsayılan depolama sınıfıdır.

{
        int Count;
        auto int Month;
}

Yukarıdaki örnek, aynı depolama sınıfına sahip iki değişkeni tanımlar. auto yalnızca işlevler içinde, yani yerel değişkenler içinde kullanılabilir.

intautoaşağıdaki kodun varsayılan türüdür :

auto Month;
/* Equals to */
int Month;

Aşağıdaki kod da yasaldır:

/* Default-int */
main()
{
    reurn 0;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.