2013-05-15 10 views
18

Sadece esasen aşağıdakileri yapar kod rastlamak ettik. Bu ne demek?Parantez içinde kapsanan değerlerin virgülle ayrılmış listesi ne anlama gelir? a = (1, 2, 3); Daha önce bu notasyonu görmedim</p> <pre><code>int a = (1, 2, 3); </code></pre> <p>:

+12

kod yazma kodu. 3 a atanır. –

+0

Birisi bunun için bir kopyasını kazıyor olsa da merak ediyorum (çünkü hiçbir şeyin olduğuna inanamıyorum). –

+1

@ChristianRau, büyük olasılıkla bir tane var - ama aslında Google'da ve arama sonuçlarında anlamlı sonuçlar veren StackOverflow'da bir arama sorgusu oluşturmaya çalıştım, çünkü operatörün adını bilmiyorum! –

cevap

36

uzun olan bu comma operator olup: 0 değerlendirilmesi, ilk olarak değerlendirilecek a, daha sonra b ve sonuç b'dur. İlk

int a = (1, 2, 3); ardından 1, 2 nihayet 3 değerlendirir ve 3 son a initialize etmek için kullanır. Burada işe yaramaz, ancak ,'un sol işleneninin yan etkileri olduğunda yararlı olabilir (genellikle: bir işlev çağrısı olduğunda).

+0

Genellikle, geçici sonuçlarla çalışan makro tanımları için özellikle kullanışlı olan '({doSomething(); x;})' gibi yazarım. Bu (alt) ifadeleri ayırmak için virgül yerine noktalı virgül kullanmamın yanı sıra, bu notasyonlar arasında bir fark var mıdır? – leemes

+2

@leemes Standart C ve C++ 'da geçersiz olan, ancak bazı ifadeler tarafından (en azından GCC) ifadelerin yalnızca ifadeler olarak kullanılmasına izin vermek için bir uzantı olarak kabul edilir, böylece yapabileceğinizden ({if (0)) {1;} 2;}) '. – hvd

+0

"genellikle: bir işlev çağrısı olduğunda" lütfen açıklayabilir misiniz? Ben soruyorum çünkü bağlam hakkında kafam karıştı. foo (T, T2), bu virgül veya foo (T), foo (T) demek istiyor musunuz? –

19

Sadece (tanıtan uygun dizisi arasında işaret) her işlenen sentezleme ardışık değerlendirir ve son bir döner comma operator kullanır. Böylece, örneğiniz aslında int a = 3;'a eşdeğerdir.

Ama C ve C++ ve fonksiyon çağrısı ifadeleri, başlatıcı listelerinde kullanılan virgül ile karıştırılmamalıdır ve diğer tüm yerlerde gerçekten az kullanılan operatörler biridir. Bu kadar nadir olmayan bir kullanım durumu, aslında aslında sözde bir virgül operatörünü kullanmayı düşünmemiş olsanız bile, döngüler için çoklu artışlar olacaktır (for(...; ...; ++i,++j)).

Bir başka yakalama kullanım durumu, tuhaf işaretçi döndürme argümanı ile eski frexp'un iyi bir uygulamasında olduğu gibi, açıklık ve açıklık uğruna tek bir ifadeye (geri dönüş gibi) birden çok kavramsal olarak ilgili ifadeyi yerleştirmeye çalışırken ortaya çıkar (uygun C++, sadece bir çift geri gerçeğini) göz ardı:

double frexp(double arg, int *exp) 
{ 
    if(...) 
     return *exp=..., result; 
    ... 
} 

daha verimli hale eşdeğer

double frexp(double arg, int *exp) 
{ 
    if(...) 
    { 
     *exp = ...; 
     return result; 
    } 
    ... 
} 
+4

Bu cevabı, şu anda hvd tarafından halihazırda en çok oy alandan daha iyi beğeniyorum, ama kiminle internette tartışacağım? ':)' –

+1

@ChristianRau [bu] 'ı hatırlayın (http://stackoverflow.com/questions/16538458/how-to-make-ix-works-as-i/16538741#16538741), bunu burada virgül kullanarak yapabilirsiniz ve örnek :-) –

+0

@Koushik Hah, sağa bakın! Hala garip, ama '' '' sürümünden daha iyi. Yine de bu cevapta göstermeyeceğim, çünkü bu gerçekten makul bir kullanım durumu olmadığı için bence. Ancak çapraz bir çapraz referans için +1. –

3

Yalnızca 1, 2 ve 3'ü değerlendirir (bunlar yalnızca değerlerdir, ancak işlev çağrıları da olabilir) ve sonuncunun değerini (veya dönüş değerini) sol işlenenine ayarlar (örneğinizde, a).

#include <stdio.h> 

int toto() 
{ 
    printf("toto()\n"); 
    return (21); 
} 

int tata() 
{ 
    printf("tata()\n"); 
    return (42); 
} 

int main() 
{ 
    int a = (toto(), tata()); 
    printf("%d\n", a); 
    return (0); 
} 

Çıktı:

toto() 
tata() 
42 

Düzenleme:

Belki bu nasıl çalıştığını anlamak yardımcı olacaktır

+0

İlgili çıktıyı ekleme özgürlüğünü aldım. –

5

O virgül operatörü Tha en C kodu, C++ içinde aynı şekilde çalışır olduğunu . C11 standardı, bu tür bir operatörün tek kullanımlık durumunu anlatır.

C11 standard 6: 5: 17

virgülle operatör

virgülle operatörünün sol işlenen bir boşluk sentezleme olarak değerlendirilir; değerlendirme ile sağ işlenenin arasında bir sıralama noktası vardır. Daha sonra sağ işlenen değerlendirilir; Sonuç tür işlevler veya listelere argümanlar olarak virgül liste halinde ayrı kalemler için kullanılan bağlamlarda görünemez bu alt açıklandığı gibi türünü ve value.114)

virgül operatörünü() (vardır başlatıcıları). Diğer taraftan, , parantez içinde ekspresyon içinde veya bu bağlamlarda bir koşullu operatörünün ikinci ifadesi içinde kullanılabilir. işlev çağrısı f (a, (t = 3 olduğunda, t + 2), c) işlevi değeri Bu comma operator olduğu 5.

3

sahip olan ikinci olan üç bağımsız değişkeni vardır. Birden çok ifadeyi "sarar", onları soldan sağa doğru değerlendirir ve tüm ifadenin değeri son alt ifadeyle belirlenir. Örneğinizde, 3 olarak değerlendirir.

Virgül operatörünün özellikle kullanışlı olduğu bir durum, örneğin bir döngü içi "artış" ifadesinde birden çok şey yapmak isterseniz, örneğin iki değişkenini arttırmadır.

Örnek: Ayrı değişkenler olarak x ve y kullanarak köşegen boyunca bir görüntüyü yineleyin. x ve y için iki ayrı değişken kullanıyorum, çünkü bunlardan birini diğerinden bağımsız olarak değiştirmek isteyebilirim (unutmayın, bu sadece aptal bir örnek). Yani bir "artım" deyiminde hem x ve y artırmak istediğiniz-döngü: For döngüsü içinde "başlatma" ifadesi virgül operatörünü kullanmaz yaptığı

for(int x = 0, y = 0; x < width && y < height; ++x, ++y) { 
    // ...          ^^^^^^^^ 
} 

Not; Sadece iki değişkenini bildirir.

+1

İlk cümledeki * "ayırıcı" * "* işlecini" * değiştirmeyi tercih ederim; çünkü ilk tercih, virgüllerin olağan dışı (non-operatör) dediğim şeydir. Ama iyi, for-loop'un başlatma ifadesi arasındaki farkı belirttiniz. –

+0

Oops, bu yine de kazaydı. Bunu işaretlediğiniz için teşekkürler;) – leemes

İlgili konular