2016-03-03 14 views
7

Mam prosty kod C i duże zamieszanie dotyczące wyrażeń zawierających operator (y) przecinka().W C, dlaczego wyrażenie (Statement) zbiegające przecinek (,) operator działa inaczej

int main(){ 
    int i=0,j=11,c; 
    c=i=j,++i; 
    printf("c=%d i=%d\n",c,i); 
    c=(i=j,++i); 
    printf("c=%d i=%d\n",c,i); 
    return 0; 
} 

Powyższe drukuje kod:

c=11 i=12 
c=12 i=12 

moje pytania są następujące:

  1. Jaka jest rzeczywista praca z przecinkiem (,) jako operatora?
  2. ++ ma wyższy priorytet niż , i =, dlaczego ocena jest wykonywana dla wyrażenia po lewej stronie przecinka?
  3. Jaka będzie kolejność, jeśli wyrażenie zawiera operatorów o innym priorytecie, czy będzie to zależne od przecinka (,)?
  4. Czy zachowuje się jak substytut średnika (;)?
+2

Nie jestem ekspertem, ale to 'c = i = j, ++ I' wygląda U.B. –

+3

@MargaretBloom Nie, operator przecinka wprowadza punkt sekwencji, IIRC. –

+0

http://stackoverflow.com/questions/2087026/effect-of-using-a-omma-instead-of-a-semi-colon-in-c-and-c – Turamarth

Odpowiedz

10

Operator przypisania ma wyższy priorytet niż operator przecinania. Zatem ekspresja

c = i = j, ++i; 

odpowiada

(c = i = j), ++i; 

Zgodnie z normą C (05/06/17 operatora przecinek)

2 Lewe argumentu operatora przecinek ocenianych jako void wyrażenie; istnieje punkt sekwencji między jego oceną a tym z prawego argumentu. Następnie prawy operand jest oceniany; wynik ma rodzaj i value.114)

W powyższym wyrażeniu wyniku operatora przecinkami odrzuca się, ale ma działanie niepożądane zwiększenie i.

W tym wyrażeniu

c = (i = j, ++i); 

spowodowane użyciem nawiasów zmieniono kolejność oceny powyższej wypowiedzi. Obecnie jest to równoważne

c = ((i = j), ++i); 

i zmienne c pobiera wartość ekspresji ++i według zacytować C standardowych wymienionych powyżej.

1

Cóż, podzielmy to. W pierwszym przypadku c i i przyjmują wartość j => c = i = j = 11; następnie zwiększasz i => i = 12; Więc kod jest równoznaczne z tym

c = j; 
i = j; 
++i; 

W drugim przypadku i przyjmuje wartość j => i = j = 11, a potem inkrementacja i => I = 12, a następnie c przyjmuje wartość i = > c = 12;

Więc kod jest równoważny do tego:

i = j; 
++i; 
c = i; 
4

operator przecinek jest wykonanie wielu oświadczenia i odesłać tylko wynik ostatniego sprawozdania.

Więc dla c=i=j,++i;: c=i=j jest wykonywany, a następnie ++i i po jest zwracana, że ​​wynikiem ++i (nie używany).

I c=(i=j,++i); według pierwszeństwa operatora i=j jest wykonywany, a tuż po ++i jest wykonywany, a następnie affectation do c w wyniku (i=j, ++i), co jest wynikiem ostatniego sprawozdania, tj ++i

Więc, zachowanie przecinka nie jest takie samo jak średnik. Możesz użyć go jako zamiennika, jak w c=i=j,++i;.

Osobiście nie zachęcają do korzystania z tego operatora, który generuje mniej czytelne i mniej utrzymaniu kod

+0

++ i jest Sporządzono po i = j dla danej instrukcji c = (i = j, ++ i); – skyconfusion

+0

@skyconfusion przepraszam, zły angielski, oczywiście jest to, że edytuję moją odpowiedź – Garf365

+0

Czy ktoś może mi wyjaśnić, dlaczego moja odpowiedź jest odrzucona, proszę? – Garf365

1

Operator przecinek będzie ocenić i odrzutów wszystkie operacje, aż do, ale nie w tym, wykonanie operacji. Pozwala to na wywoływanie dowolnej liczby niesekwencyjnych operacji w jednym wierszu, w którym interesująca jest tylko ostatnia operacja.

Pomyśl o tym w ten sposób, jeśli masz kilka zmiennych pętli do zwiększenia w dowolnym miejscu w pętli, możesz oddzielić wszystkie dodatki/odejmowanie, itd. Od własnych indywidualnych zmiennych w oddzielnym wierszu, ale czemu?Gdzie są wykonywane (w granicach rozsądku) jest bez konsekwencji na działanie kodu. Następnie można je wywołać w jednej linii bez negatywnego wpływu na kod.

+1

Operator przecinka ma tylko 2 operandy, więc po prostu odrzuci wynik lewego argumentu i użyje wyniku Ten dobry, ten wlasciwy. Właściwa jest zawsze ostateczna. – Lundin

+0

"Następnie można je wywoływać w jednej linii bez negatywnego wpływu na kod." Nie, naprawdę nie mogą. Ten kod 'for (int i = 0, int j = 0, int k = 0; i Lundin

+1

@ Bzdury o nonsense. Oczywiście możesz mieć więcej niż jeden iterator pętli w pętli. C nie jest BASIC, a iteratory pętli nie mają specjalnego statusu; pętla for ma tylko trzy rogi. Twój drugi przykładowy kod pójdzie źle, jeśli chcesz użyć 'continue', a to daje' j' i 'k' niepotrzebnie duży zakres. –

2

Jaka jest faktyczna praca przecinka (,) jako operatora?

Operator przecinka jest głównie zbędny. See this po opis działania.

++ ma wyższy priorytet niż i = dlaczego ocena jest wykonywana dla wyrażenia po lewej stronie przecinka? Jaka będzie kolejność, jeśli wyrażenie zawiera operatorów o innym priorytecie, czy będzie to zależało od przecinka (,)?

Lewy operand jest oceniany pod kątem skutków ubocznych. Wynik operatora przecinka jest wynikiem ocenionego prawego argumentu. Należy zauważyć, że operator przecinka ma najniższy priorytet wszystkich operatorów w C.

Czy zachowuje się jak substytut średnika (;)?

Rodzaj, tak. Zarówno średnik, jak i operator przecinka zawierają punkt sekwencji. Różnica polega na tym, że operator przecinka nie jest końcem instrukcji, więc może zostać ściśnięty z innymi operatorami w tej samej linii, a także zwraca wynik.

Nie ma powodu, dla którego kiedykolwiek byś chciał to zrobić. Głównym zastosowaniem operatora przecinka jest zaciemnianie kodu, należy go unikać.Jedynym powodem, dla którego musisz się nauczyć, jak to działa, jest to, że możesz napotkać kod zawierający go.

Na przykład kod nonsens powinny być zapisane w coś bardziej czytelnego i bezpieczny:

int main(){ 
    int i=0; 
    int j=11; 
    int c; 

    i=j; 
    c=j; 
    i++; 
    printf("c=%d i=%d\n",c,i); 

    i=j; 
    i++; 
    c=i; 
    printf("c=%d i=%d\n",c,i); 

    return 0; 
} 
+1

'// i = j; // zbędne, już to zrobiliśmy, dlaczego to zrobić ponownie? 'nie jest poprawne, ponieważ istnieje' i ++ 'powyżej, więc faktycznie skończyłoby się' c = 11, i = 12', a następnie 'c = 13 , i = 13' –

+0

@NeilTwist Ah tak, naprawione. – Lundin

Powiązane problemy