int a [] = {1,2,}; Tuhaf virgül kullanılmasına izin verildi. Belirli bir nedeni var mı?


335

Belki ben bu gezegenden değilim, ama bana öyle geliyor ki bir sözdizimi hatası olmalı:

int a[] = {1,2,}; //extra comma in the end

Ama değil. Bu kod Visual Studio üzerinde derlenmiş zaman şaşırdı, ama ben standardını kontrol ve uzak C ++ kurallar söz konusu olduğunda, bu nedenle MSVC derleyici güvenmemeyi öğrendim olduğu standardı tarafından izin de. Bana inanmıyorsanız dilbilgisi kuralları için 8.5.1'i görebilirsiniz.

resim açıklamasını buraya girin

Buna neden izin veriliyor? Bu aptalca bir işe yaramaz soru olabilir ama neden sorduğumu anlamanızı istiyorum. Genel bir dilbilgisi kuralının alt vakası olsaydı, anladım - genel dilbilgisini, bir başlangıç ​​listesinin sonunda gereksiz bir virgüle izin vermemek için daha zor hale getirmeye karar verdiler. Ancak hayır, ek virgüle açıkça izin verilir. Örneğin, (işlevi alan bir fonksiyon çağrısı bağımsız değişken listesinin sonuna fazladan bir virgül izin verilmez ...), normal .

Peki, yine, bu gereksiz virgülün açıkça izin verilmesinin belirli bir nedeni var mı?


10
Her biri 'yeni satır eklemeyi kolaylaştırmayı' kabul ediyor gibi görünüyor - ancak dil özelliklerini tanımlayan insanlar bu tür şeyler hakkında gerçekten rahatsız mı? Eğer gerçekten bu anlayışlarsa, bir ;sonraki belirteç açık olduğunda neden bir eksiki görmezden gelmiyorlar aslında bir sonraki ifadedir.
YetAnotherUser

35
@YetAnotherUser: Evet, dil tasarımcıları böyle şeyler düşünüyor. Noktalı virgül bırakmanıza izin vermek çok daha büyük bir etkiye sahip olacaktır ve dilin birçok bölümünde oldukça belirsiz olacaktır (unutmayın, boşluk C'de anlamsal değildir). Ek bir virgül, bu durumun belirsiz olmamasıdır. Fazladan bir noktalı virgül neredeyse hiç belirsiz değildir ve buna izin verilir. Belirsiz olduğu durumda ( for()örneğin bir sonra ), eklemek derleyici uyarısı verir.
Rob Napier

5
@Tomalak: Bir insan okuyucu için belirsizdir ve genellikle bir hatadır. Bu yüzden bir uyarı veriyor. Benzer şekilde if (x = 1)gramerde belirsiz değildir, ancak insanlar için çok belirsizdir ve bu nedenle bir uyarı verir.
Rob Napier

12
@Rob: Örneğiniz ifde belirsiz değil. "Belirsiz" in ne anlama geldiğini düşündüğün anlamına gelmiyorum!
Orbit'te Hafiflik Yarışları

5
Derleyicinin bizi korumak için yararlı bir şey olduğunu kabul ettiğimiz sürece, bir dizi bildirimindeki sondaki virgül, derleyicinin bizi korumak için yararlı bir şey değildir.
Rob Napier

Yanıtlar:


436

Kaynak kodu oluşturmayı ve daha sonraki bir tarihte kolayca genişletilebilen kod yazmayı kolaylaştırır. Ek bir giriş eklemek için nelerin gerekli olduğunu düşünün:

int a[] = {
   1,
   2,
   3
};

... Varolan hattına virgül eklemek zorunda ve yeni bir satır ekleyin. Bunu, üçünün zaten bir virgülün bulunduğu durumda , sadece bir satır eklemeniz gereken durumla karşılaştırın . Benzer şekilde, bir satırı kaldırmak isterseniz, son satır olup olmadığından endişe etmeden bunu yapabilirsiniz ve virgüllerle uğraşmadan satırları yeniden sıralayabilirsiniz. Temel olarak, çizgilere nasıl davrandığınız konusunda tekdüzelik olduğu anlamına gelir.

Şimdi kod oluşturmayı düşünün. Gibi bir şey (sözde kod):

output("int a[] = {");
for (int i = 0; i < items.length; i++) {
    output("%s, ", items[i]);
}
output("};");

Yazdığınız mevcut öğenin ilk veya son olup olmadığı konusunda endişelenmenize gerek yok. Çok daha basit.


89
Ayrıca, bir VCS kullanırken, bir öğe eklendiğinde veya kaldırıldığında yalnızca bir satır değiştiğinden, iki sürüm arasındaki "fark" daha temizdir.
Kevin Panko

47
@ Néstor: Neden "talihsiz"? Buradaki dezavantaj nedir? Sadece dilin küçük bir kısmı için kod üretimine (ve kolay manipülasyona) biraz önem verilmesi , dilin tüm kararlarının ardındaki birincil motivasyon olması gerektiği anlamına gelmez. Tür çıkarımı, noktalı virgüllerin kaldırılması vb . Dil üzerinde büyük etkiler yaratır . Burada yanlış bir ikilik oluşturuyorsun, IMO.
Jon Skeet

18
@ Néstor: İşte pragmatizm dogmatizmi kazanıyor: neden her ikisinin bir karışımı olmak daha yararlı olduğunda, neden tamamen bir şey veya tamamen diğeri olmak zorunda? Sonunda virgül ekleyebilmek aslında nasıl yoluna giriyor? Bu sizi herhangi bir anlamda engelleyen bir tutarsızlık mı? Değilse, lütfen bu alakasız uygunsuzluğu , sonunda virgül kullanmanın pratik faydalarına karşı tartın .
Jon Skeet

8
@Mrchief: Bu bir yazma oranı meselesi değil - öğeleri kopyalarken, çıkarırken veya yeniden sıralarken basitlik meselesi. Dün hayatımı kolaylaştırdı. Hiç dezavantajı ile neden değil hayatı kolaylaştıran? MS'e parmağınızı göstermeye çalışırken, Microsoft'un varlığından önce bunun C'de olduğundan şüpheleniyorum ... Bu gerekçenin garip olduğunu söylüyorsunuz, ancak her gün yüzlerce şirkette binlerce geliştiriciye fayda sağladığını iddia ediyorum. Bu, derleyici yazarlarına fayda sağlayan bir şey aramaktan daha iyi bir açıklama değil mi?
Jon Skeet

6
Bu K&R C idi.
Ferruccio

126

Böyle bir şey yaparsanız yararlı olur:

int a[] = {
  1,
  2,
  3, //You can delete this line and it's still valid
};

6
JavaScript bu sözdizimini destekler: bu var a = [1, 2,];yüzden bildiğim diğer birçok dilde ... ActionScript, Python, PHP.
Sean Fujiwara

14
@Sean IE JavaScript'te bir ayrıştırma hatasına neden olur, bu yüzden dikkat!
Skilldrick

10
IE9'da benim için değil. Ama garip bir şey yapıyor ... boş bir eleman yaratıyor. Dikkat edeceğim.
Sean Fujiwara

5
@Sean Maalesef haklısınız - bu IE'de bir çözümleme hatası değil, ama olacak fazladan bir eleman setini yerleştirin undefined.
Skilldrick

3
En sinir bozucu olan JSON bu sözdizimini desteklemiyor.
Timmmm

38

Geliştirici için kullanım kolaylığı olduğunu düşünüyorum.

int a[] = {
            1,
            2,
            2,
            2,
            2,
            2, /*line I could comment out easily without having to remove the previous comma*/
          }

Ayrıca, herhangi bir nedenle sizin için kod üreten bir aracınız varsa; aracın başlangıçtaki son öğe olup olmadığına dikkat etmesi gerekmez.


32

Her zaman ekstra öğeler eklemeyi kolaylaştırdığını varsaydım:

int a[] = {
            5,
            6,
          };

basitçe olur:

int a[] = { 
            5,
            6,
            7,
          };

daha sonraki bir tarihte.


3
Düzenlemeyi biraz daha hızlı yapmanın sözdizimini bozmak için iyi bir neden olduğunu düşünmüyorum. IMHO bu sadece bir başka garip C ++ özelliğidir.
Giorgio

3
@Giorgio: Eh, C'den miras alındı. Orijinal dil spesifikasyonunda sadece bir gözetim olması, yararlı bir yan etkiye sahip olması tamamen mümkündür.
Oliver Charlesworth

Tamam, C'den geldiğini bilmiyordum. Sadece Java'da da izin verildiğini kontrol ettim. Yine de biraz garip geliyor: sezgimde virgül bir sonlandırıcı değil bir ayırıcıdır. Ayrıca, son virgül atlamak da mümkündür. Yani, bir sonlandırıcı, bir ayırıcı veya her ikisi mi? Ama tamam, bu özellik mevcut ve bilmek güzel.
Giorgio

11
@Giorgio - kaynak kodu makineler içindir, insanlar içindir. Bizi basit transpozisyon hataları yapmaktan alıkoyan küçük şeyler bir nimettir, bir gözetim değil. Başvuru için, PHP ve ECMAScript'te (ve dolayısıyla JavaScript ve ActionScript) de bu şekilde çalışır, ancak JavaScript nesne gösterimlerinde (JSON) geçersizdir (örn. Tamamdır [1,2,3,], ancak {a:1, b:2, c:3,}değildir).
Dereleased

1
@Groky: Bu konuda ne kadar çok düşünürsem, bir programlama dilinin sözdiziminin mümkün olduğunca basit ve tutarlı olması ve mümkün olduğunca az istisna dışında olması gerektiğine ikna olurum: bu, dili öğrenmeyi kolaylaştırır (hatırlanması gereken daha az kural) ). Bir listeye / listeden bir öğe eklerken / listeden öğe kaldırırken bir veya iki tuş vuruşunu kaydetmenin avantajı (bu arada, kodlamayı harcadığım toplam süreye kıyasla bunu sık sık yapmıyorum) bana kıyasla oldukça önemsiz görünüyor açıkça tanımlanmış bir sözdizimine sahip olmak.
Giorgio

21

Herkesin satır ekleme / çıkarma / oluşturma kolaylığı hakkında söylediği her şey doğrudur, ancak bu sözdiziminin parladığı gerçek yer, kaynak dosyaları bir araya getirirken. Bu diziye sahip olduğunuzu düşünün:

int ints[] = {
    3,
    9
};

Ve bu kodu bir havuzda kontrol ettiğinizi varsayalım.

Sonra arkadaşınız onu düzenler, sonuna ekler:

int ints[] = {
    3,
    9,
    12
};

Ve başlangıca ekleyerek aynı anda düzenlersiniz:

int ints[] = {
    1,
    3,
    9
};

Anlamsal olarak bu tür işlemler (başlangıca ekleme, sonuna ekleme) tamamen güvenli olmalı ve sürüm yazılımınız (umarım git) otomasyona geçebilmelidir. Ne yazık ki, durum böyle değil çünkü 9'unuzdan sonra sürümünüzde virgül yok ve arkadaşınız var. Oysa, orijinal versiyonda izleyen 9 varsa, otomatikleştirilirdi.

Yani, temel kuralım: Liste birden fazla satıra yayılıyorsa, virgül kullan, liste tek bir satırdaysa kullanmayın.


15

Sondaki virgül, geriye dönük uyumluluk nedeniyle izin verildiğine inanıyorum. Sonunda virgül koyan, öncelikle otomatik olarak oluşturulan birçok kod var. Sonunda özel koşul olmadan bir döngü yazmayı kolaylaştırır. Örneğin

for_each(my_inits.begin(), my_inits.end(),
[](const std::string& value) { std::cout << value << ",\n"; });

Programcı için gerçekten bir avantaj yok.

PS Bu şekilde kodu otomatik olarak oluşturmak daha kolay olsa da, aslında her zaman sondaki virgül koymamaya dikkat ettim, çabalar asgari, okunabilirlik geliştirildi ve bu daha önemli. Kodu bir kez yazarsınız, birçok kez okursunuz.


5
Tamamen katılmıyorum; [Bence] tam olarak C'den sonra oluşturulan birçok dile doğru yolunu buldu, çünkü programcının dizinin içeriğinde dolaşabilmesi, satırları willy-nilly gibi yorum yapabilmesi avantajlı olduğu için, saçma transpozisyona bağlı sözdizimi hataları hakkında endişelenmenize gerek kalmadan Zaten yeterince stresli değil miyiz?
Dereleased

12
@Dereleased - Aynı mantıkla, (bir şey) gerisinde olmamalıdır neden nasıl, izin verilmesi int a = b + c +;veya if(a && b &&);sadece yazma kodu jeneratörlere sonunda bir şey ve daha kolay kopyalayıp yapıştırmak daha kolay olacaktır. Bu sorun hem önemsiz hem de özneldir, bu gibi durumlarda kod okuyucu için en iyisini yapmak her zaman iyidir.
Gene Bushuyev

1
@Gene Bushuyev: Kesinlikle! Genellikle + veya && ile uzun ifadeler alıyorum, satırın sonunda operatör var ve elbette, ifadenin son işlenenini kaldırmak istediğimde fazladan zaman harcamak zorundayım. Bu virgül sözdiziminin gerçekten tuhaf olduğunu düşünüyorum!
Giorgio

2
@GeneBushuyev - Onlara katılmıyorum. Diziler ve benzerlerinde virgüllerin kullanılmasına izin verirken hata giderici bir özelliktir ve hayatınızı bir programcı olarak kolaylaştırırken, okunabilirlik için saflık açısından, takip eden AND (&&) ifadelerini, artıları ve diğer çeşitli operatörleri koşulludan kaldırmak için önlemler alırım ifadeleri. Sadece çirkin, IMO.
Sune Rasmussen

2
&&Operatörle ilgili olarak , bazen gerektiği gibi if (true \n && b1 \n && b2)satır ekleyip kaldırabilmem için şartlı koşullar yaparım .
Christian Mann

12

Bildiğim kadarıyla bu izin verilen nedenlerden biri otomatik kod oluşturmak için basit olması gerektiğidir; son eleman için özel bir işleme ihtiyacınız yoktur.


11

Dizileri veya numaralandırmaları dışarı veren kod üreticilerini kolaylaştırır.

Hayal etmek:

std::cout << "enum Items {\n";
for(Items::iterator i(items.begin()), j(items.end); i != j; ++i)
    std::cout << *i << ",\n";
std::cout << "};\n";

Yani, sondaki virgülün tükürülmesini önlemek için ilk veya son öğenin özel bir şekilde işlenmesine gerek yoktur.

Örneğin, kod üreteci Python'da yazıldıysa, aşağıdaki virgül str.join()işlevini kullanarak tükürmeyi önlemek kolaydır :

print("enum Items {")
print(",\n".join(items))
print("}")

10

Bunca zamandan sonra hiç kimse Açıklamalı C ++ Referans Kılavuzu'nu ( ARM ) alıntılamadı , vurgulu mayınla [dcl.init] hakkında aşağıdakileri söylüyor :

Başlatmalar için açıkça çok fazla gösterim var, ancak her biri belirli bir kullanım tarzına iyi hizmet ediyor gibi görünüyor. = {İnitializer_list, tercih} gösterimde C miras kalan ve veri yapıları ve dizilerin başlatma için de hizmet eder. [...]

Her ne kadar ARM yazıldığından beri dilbilgisi evrimleşmiş olsa da başlangıç ​​noktası kalmıştır.

ve C'de buna neden izin verildiğini görmek için C99 mantığına gidebiliriz ve şöyle diyor:

K&R, bir başlatıcı listesinin sonunda bir başlatıcıda sondaki virgüllere izin verir. Standart, bir başlangıç ​​listesi eklemek veya listeden üye silmek için esneklik sağladığı ve bu tür listelerin makine üretimini basitleştirdiği için bu sözdizimini korumuştur .


1
Literatürün en yedek cevabı ve bu özelliğin gerçek kaynağı için oy verin.
Marko

10

Diğer cevaplarda belirtilmeyen bir kullanım durumu görüyorum, favori Makrolarımız:

int a [] = {
#ifdef A
    1, //this can be last if B and C is undefined
#endif
#ifdef B
    2,
#endif
#ifdef C
    3,
#endif
};

Son işlemek için makrolar eklemek ,büyük acı olur. Sözdizimindeki bu küçük değişiklikle, bu yönetilmesi önemsizdir. Ve bu, makine tarafından üretilen koddan daha önemlidir, çünkü Turing'in tam dilde yapılması genellikle çok sınırlı ön işlemciden daha kolaydır.


7

Uygulamada * izin verilmediği tek dil Javascript'tir ve sayısız soruna neden olur. Örneğin, dizinin ortasından bir çizgi kopyalayıp yapıştırırsanız, sonuna yapıştırır ve virgül kaldırmayı unutursanız, siteniz IE ziyaretçileriniz için tamamen bozulur.

* Teoride izin verilir, ancak Internet Explorer standardı takip etmez ve hata olarak kabul eder


JavaScript'in "dizileri" (yalnızca sihirli uzunluk özelliğine sahip nesneler) zaten oldukça sıra dışı: var x = [,,,]yasal (IE <9 hariç, ancak teknik özellik yasal olduğunu söylüyor)
Peter C

ECMAScript spesifikasyonuna göre, tamamen geçerlidir; teoride, söz konusu spesifikasyona göre, özellikle burada bulunan spesifikasyonun bir kısmına göre JavaScript'i uygulayan herhangi bir tarayıcıda çalışmalıdır .
Dereleased

1
Ne yazık ki JavaScript tamamen herkes için uygulama yapmakla ilgilidir. Bu nedenle hayır, ~% 50 kullanıcılarının uygulamanızı kullanırken sorun yaşadıkları zaman geçerli değildir. Ve evet, eğer yapabilirsem IE <9 yasaklıyordum - sadece orada çalışmak için iyi kodlar yapmak için çok fazla saat harcıyorum ...
kgadek

@Dere: evet, cevabımda çok şey söyledim =)
Thomas Bonini

@Deleleased microsoft, kendi teknik özelliklerini icat ediyor ve diğerlerinin en azından zihniyetin değiştiğine uymasını emrediyor (şükür)
Chris McGrath

7

Makineler için daha kolay, yani kodların ayrıştırılması ve oluşturulması. İnsanlar için, yani değişiklik, yorum yapma ve görsel zarafet gibi tutarlılık için daha kolaydır.

C varsayarsak, aşağıdakileri yazar mısınız?

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    puts("Line 1");
    puts("Line 2");
    puts("Line 3");

    return EXIT_SUCCESS
}

Hayır. Sadece son ifade bir hata olduğu için değil, aynı zamanda tutarsız olduğu için. Öyleyse neden koleksiyonlar için aynı şey geçerli? Son noktalı virgülleri ve virgülleri atlamanıza izin veren dillerde bile, topluluk genellikle bunu sevmez. Örneğin Perl topluluğu, noktalı virgülleri atlamaktan hoşlanmıyor gibi görünüyor, tek katmanlı çubuklar. Bunu virgüllere de uygularlar.

Çok satırlı kod blokları için noktalı virgül kullanmazsanız, çok satırlı koleksiyonlarda virgül kullanmayın. Yani, dil izin verse bile yapmazdın, değil mi? Sağ?


Buna izin veren diller (ör. Pascal) vardır. Yani aralarından seçim yapmanız gerekiyor; bir sonlandırıcı (C) veya bir ayırıcı (Pascal) olarak. Aynısı ','. ',' Bir sonlandırıcıysa, ancak {1, 2, 3} bir sözdizimi hatası olması benim için uygun olur.
Giorgio

6

Nedeni önemsiz: satır ekleme / çıkarma kolaylığı.

Aşağıdaki kodu düşünün:

int a[] = {
   1,
   2,
   //3, // - not needed any more
};

Artık, bazen virgül eklemek / kaldırmak zorunda kalmadan listeye kolayca öğe ekleyebilir / kaldırabilirsiniz.

Diğer cevapların aksine, gerçekten liste oluşturma kolaylığı geçerli bir neden olduğunu düşünmüyorum: sonuçta, özel durum için son (veya ilk) satır için kod önemsizdir. Kod oluşturucular bir kez yazılır ve birçok kez kullanılır.


6

Her çizginin aynı formu izlemesini sağlar. Öncelikle bu, yeni satır eklemeyi kolaylaştırır ve değişikliği anlamlı bir şekilde takip eden bir sürüm kontrol sistemine sahip olmasını sağlar ve ayrıca kodu daha kolay analiz etmenizi sağlar. Teknik bir sebep düşünemiyorum.


5

Bunun, öğeleri uzun bir listede hareket ettirmekten kaynaklanan hatalardan korunmasına izin verilir.

Örneğin, şöyle bir kodumuz olduğunu varsayalım.

#include <iostream>
#include <string>
#include <cstddef>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof *(array))
int main() {
    std::string messages[] = {
        "Stack Overflow",
        "Super User",
        "Server Fault"
    };
    size_t i;
    for (i = 0; i < ARRAY_SIZE(messages); i++) {
        std::cout << messages[i] << std::endl;
    }
}

Stack Exchange sitelerinin orijinal üçlemesini gösterdiği için harika.

Stack Overflow
Super User
Server Fault

Ancak bununla ilgili bir sorun var. Görüyorsunuz, bu web sitesindeki altbilgi Süper Kullanıcıdan Önce Sunucu Hatası gösteriyor. Herkes fark etmeden daha iyi düzeltin.

#include <iostream>
#include <string>
#include <cstddef>
#define ARRAY_SIZE(array) (sizeof(array) / sizeof *(array))
int main() {
    std::string messages[] = {
        "Stack Overflow",
        "Server Fault"
        "Super User",
    };
    size_t i;
    for (i = 0; i < ARRAY_SIZE(messages); i++) {
        std::cout << messages[i] << std::endl;
    }
}

Sonuçta, hareket eden çizgiler o kadar zor olamazdı, değil mi?

Stack Overflow
Server FaultSuper User

Biliyorum, "Server FaultSuper User" adında bir web sitesi yok, ancak derleyicimiz var olduğunu iddia ediyor. Şimdi sorun, C'nin iki çift tırnaklı dize yazmanıza ve bunları hiçbir şey kullanmadan birleştirmenize izin veren bir dize birleştirme özelliğine sahip olmasıdır ( -işaretin birden çok anlamı olduğu için tamsayılarda da benzer bir sorun olabilir ).

Peki ya orijinal dizinin sonunda işe yaramazsa virgül varsa? Çizgiler hareket edecekti, ama böyle bir hata olmazdı. Virgül kadar küçük bir şeyi kaçırmak kolaydır. Her dizi öğesinden sonra virgül koymayı hatırlarsanız, bu hata gerçekleşemez. Sen sen virgül sorunlarının nedenidir bulacağını kadar şey ayıklama dört saat harcamak istemem .


4

Birçok şey gibi, bir dizi başlatıcısındaki sondaki virgül C ++ 'ın C'den devralınan şeylerden biridir (ve sonsuza dek desteklemesi gerekecektir). "Derin C sırları" kitabında , buraya yerleştirilenlerden tamamen farklı bir görünümden bahsediliyor .

Burada birden fazla "virgül paradoksu" bulunan bir örnek var:

char *available_resources[] = {
"color monitor"           ,
"big disk"                ,
"Cray"                      /* whoa! no comma! */
"on-line drawing routines",
"mouse"                   ,
"keyboard"                ,
"power cables"            , /* and what's this extra comma? */
};

Biz okuyoruz :

... son başlatıcıdan sonra sondaki virgül bir yazım hatası değil , sözdiziminde bir Aborijin C'den taşınan bir çarpmadır . Varlığına veya yokluğuna izin verilir, ancak hiçbir önemi yoktur . ANSI C mantığında iddia edilen gerekçe, otomatik C üretimini kolaylaştırmasıdır. Enum bildirimlerinde olduğu gibi her virgül-sepa derecelendirmeli listede veya tek bir bildiride birden çok değişkenli bildiricide izleyen virgüllere izin verilirse talep daha güvenilir olacaktır . Onlar değil.

... bu bana daha mantıklı geliyor


2
enumDavada virgül yasağı biraz ilginçtir, çünkü eksik virgülün en az belirsizliği gösterdiği durum budur. Verilen struct foo arr[] = {{1,2,3,4,5}, {3,4,5,6,7}, }; dilin atayabileceği iki anlamlı anlam vardır: iki öğeli bir dizi oluşturun veya son öğenin varsayılan değerlere sahip olduğu üç öğeli bir dizi oluşturun. C daha sonraki yorumu benimsemiş olsaydı, enum foo {moe, larry, curly, };(virgül olmadan) ifadeyi yazmanın sadece bir yolu olması gerektiği prensibini yasakladığını görebiliyordum , ama ...
supercat

1
... C'nin, makul bir şekilde (ancak orada yasaklamak lehine güçlü bir argüman olarak) atanmış olabileceği (ancak verilmediği) bir durumda virgül görmezden gelmeye istekli olduğu göz önüne alındığında, 't virgül bir anlamı olabilecek bir durumda hazır [bile bir yorumlanır enum foo {moe,,larry,curly,};arasında bir sayı atlama gibi moeve larrybu sondaki virgül işleme ya da göz ardı olup olmadığını genel olarak önemli değildir, olacaktır. Önemli olabileceği tek durum, son öğenin beyan edilen türü için maksimum değer olması ve ...
supercat

1
... son atanan numaralandırma değerinin ardından meydana gelen taşmanın göz ardı edilmesi gerektiğini söyleyerek halledilebilir.
supercat

@supercat C # gibi, a priori tasarım araştırmasının IDE özelliklerini ve dili geliştirirken entegrasyonu göz önünde bulundurarak gittiği diller vardır. C bu dillerden biri değildi (ve olamazdı).
Nikos Athanasiou

C # gibi dillerde bile, değişen tasarım hedefleri oldukça ciddi tasarım tutarsızlıklarıyla sonuçlanmıştır. Örneğin, dil, normal yöntemler ve operatörler için herhangi bir geri dönüş tipi aşırı yüklemeyi desteklemekten kaçındı (temel çerçeve bunu destekleyebilse bile), çünkü derlenmesi kolay bir dile sahip olma hedefinin aksine görüldü, ancak lambda değerlendirmesi, çözünürlüğü NP-tam olan tür çıkarsama kurallarını içerir. Yeni yöntem / operatör aşırı yükleme kuralları eklemek mevcut kodu kırabilir (ancak iyi kuralların bu tehlikeyi en aza indirgeyeceğini düşünüyorum) ...
Supercat

2

Kod oluşturma ve düzenleme kolaylığına ek olarak, bir ayrıştırıcı uygulamak istiyorsanız, bu tür dilbilgisi uygulamak daha basit ve kolaydır. C #, bu kuralı, bir enumtanımdaki öğeler gibi, virgülle ayrılmış öğeler içeren bir liste izler .


1

Yalnızca bir satır eklemeniz gerektiğinden kod oluşturmayı kolaylaştırır ve son girişi özel bir durum gibi eklemeyi düşünmenize gerek yoktur. Bu özellikle kod oluşturmak için makrolar kullanıldığında geçerlidir. Dilden makro ihtiyacını ortadan kaldırmaya çalışmak için bir itme var, ancak dilin birçoğu makrolar mevcutken el ele gelişti. Ek virgül, aşağıdakiler gibi makroların tanımlanmasına ve kullanılmasına izin verir:

#define LIST_BEGIN int a[] = {
#define LIST_ENTRY(x) x,
#define LIST_END };

Kullanımı:

LIST_BEGIN
   LIST_ENTRY(1)
   LIST_ENTRY(2)
LIST_END

Bu çok basitleştirilmiş bir örnektir, ancak genellikle bu model makrolar tarafından gönderim, mesaj, etkinlik veya çeviri haritaları ve tabloları gibi şeyleri tanımlamak için kullanılır. Sonunda virgül kullanılmasına izin verilmezse, özel bir şeye ihtiyacımız olurdu:

#define LIST_LAST_ENTRY(x) x

ve bu kullanımı çok garip olurdu.


0

Böylece, iki kişi ayrı dallardaki bir listeye yeni bir öğe eklediğinde Git değişiklikleri düzgün bir şekilde birleştirebilir, çünkü Git satır bazında çalışır.


-4

Belirtilen uzunlukta olmayan bir dizi kullanırsanız, VC ++ 6.0 uzunluğunu otomatik olarak belirleyebilir, bu nedenle "int a [] = {1,2,};" kullanırsanız a uzunluğu 3'tür, ancak sonuncusu Başlatılmadıysa, "cout <


Bu, standarda uygun olmayan VC6 için bir hata mıdır?
Thomson
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.