Co robi ,
operator w C?
c
operators
comma-operator
lillq
źródło
źródło
Odpowiedzi:
Ekspresja:
Obliczane jest najpierw wyrażenie1, następnie wyrażenie2, a wartość wyrażenia2 jest zwracana dla całego wyrażenia.
źródło
i
miał wartości 5, 4, 3, 2 ani 1. Jest to po prostu 0. Jest praktycznie bezużyteczne, chyba że wyrażenia mają skutki uboczne.i = b, c;
jest równoważne z(i = b), c
ponieważ przypisanie=
ma wyższy priorytet niż operator przecinka,
. Operator przecinka ma najniższy priorytet ze wszystkich.expression1, expression2;
najpierwexpression1
jest oceniany, przypuszczalnie pod kątem skutków ubocznych (takich jak wywołanie funkcji), potem jest punkt sekwencji, następnieexpression2
jest oceniany i zwracana wartość…Widziałem najczęściej używane w
while
pętlach:Wykona operację, a następnie wykona test oparty na efekcie ubocznym. Innym sposobem byłoby zrobienie tego w ten sposób:
źródło
while (read_string(s) && s.len() > 5)
. Oczywiście to nie zadziała, jeśliread_string
nie ma wartości zwracanej (lub nie ma sensownej wartości). (Edycja: Przepraszamy, nie zauważyłem, ile lat miał ten post.)while (1)
zbreak;
oświadczeniem w treści. Próba wymuszenia przełamania fragmentu kodu w trakcie testu while lub w dół do testu do-while jest często stratą energii i sprawia, że kod jest trudniejszy do zrozumienia.while(1)
ibreak
;Operator przecinek oceni lewy argument, odrzucić wynik, a następnie ocenić prawy operand i że będzie wynik. Idiomatycznym zastosowanie, jak wspomniano w łączu przy inicjalizacji zmiennych stosowanych w
for
pętlę i daje następujący przykład:W przeciwnym razie nie ma wielu świetnych zastosowań operatora przecinka , chociaż łatwo jest nadużywać generowania kodu, który jest trudny do odczytania i utrzymania.
Z wersji roboczej standardu C99 gramatyka wygląda następująco:
a ust. 2 mówi:
Przypis 97 mówi:
co oznacza, że nie możesz przypisać do wyniku operatora przecinka .
Należy zauważyć, że operator przecinka ma najniższy priorytet i dlatego istnieją przypadki, w których użycie
()
może spowodować dużą różnicę, na przykład:będzie miał następujący wynik:
źródło
Operator przecinka łączy dwa wyrażenia po obu stronach w jedno, oceniając je w kolejności od lewej do prawej. Wartość po prawej stronie jest zwracana jako wartość całego wyrażenia.
(expr1, expr2)
jest jak,{ expr1; expr2; }
ale możesz użyć wynikuexpr2
w wywołaniu funkcji lub przypisaniu.Często występuje w
for
pętlach w celu zainicjowania lub utrzymania wielu zmiennych, jak poniżej:Poza tym użyłem go tylko "w gniewie" w jednym innym przypadku, kiedy pakowałem dwie operacje, które zawsze powinny iść razem w makro. Mieliśmy kod, który kopiował różne wartości binarne do bufora bajtów w celu wysłania w sieci, a wskaźnik utrzymywał się w miejscu, w którym doszliśmy do:
Tam, gdzie wartości były
short
s lubint
s, zrobiliśmy to:Później przeczytaliśmy, że nie było to naprawdę poprawne C, ponieważ
(short *)ptr
nie jest już wartością l i nie może być zwiększane, chociaż nasz kompilator w tamtym czasie nie miał nic przeciwko. Aby to naprawić, podzieliliśmy wyrażenie na dwie części:Jednak to podejście polegało na tym, że wszyscy deweloperzy pamiętali o umieszczaniu obu instrukcji przez cały czas. Chcieliśmy funkcji, w której można by przekazać wskaźnik wyjściowy, wartość i typ wartości. Ponieważ jest to C, a nie C ++ z szablonami, nie moglibyśmy mieć funkcji, która przyjmuje dowolny typ, więc zdecydowaliśmy się na makro:
Korzystając z operatora przecinka, mogliśmy użyć tego w wyrażeniach lub jako oświadczenia, jak chcieliśmy:
Nie sugeruję, że którykolwiek z tych przykładów jest dobry! Rzeczywiście, wydaje mi się, że pamiętam Code Complete Steve'a McConnell'a, który odradzał nawet używanie operatorów przecinków w
for
pętli: dla czytelności i łatwości utrzymania pętla powinna być kontrolowana tylko przez jedną zmienną, a wyrażenia wfor
samej linii powinny zawierać tylko kod sterujący pętlą, a nie inne dodatkowe bity inicjalizacji lub utrzymania pętli.źródło
Powoduje ocenę wielu instrukcji, ale wykorzystuje tylko ostatnią jako wartość wynikową (chyba rvalue).
Więc...
powinno skutkować ustawieniem x na 8.
źródło
Jak wskazywały wcześniejsze odpowiedzi, program ocenia wszystkie stwierdzenia, ale używa ostatniego jako wartości wyrażenia. Osobiście uważam, że jest to przydatne tylko w wyrażeniach pętli:
źródło
Jedynym miejscem, w którym widziałem, że jest przydatny, jest pisanie funkowej pętli, w której chcesz zrobić wiele rzeczy w jednym z wyrażeń (prawdopodobnie wyrażeniu init lub wyrażeniu pętli. Coś w rodzaju:
Przepraszam, jeśli są jakieś błędy składniowe lub jeśli dodałem coś, co nie jest ścisłe C. Nie twierdzę, że operator, jest dobrą formą, ale do tego można go użyć. W powyższym przypadku prawdopodobnie użyłbym
while
pętli, aby wiele wyrażeń na init i loop było bardziej oczywiste. (I zainicjowałbym i1 i i2 inline zamiast deklarować, a następnie inicjalizować ... bla bla bla.)źródło
Wracam do tego po prostu, aby odpowiedzieć na pytania @Rajesh i @JeffMercado, które moim zdaniem są bardzo ważne, ponieważ jest to jedno z najpopularniejszych haseł wyszukiwarek.
Weźmy na przykład następujący fragment kodu
To się wydrukuje
i
Przypadek jest traktowany jako wyjaśnione przez większość odpowiedzi. Wszystkie wyrażenia są obliczane w kolejności od lewej do prawej, ale tylko ostatnie jest przypisanei
. Wynik(
wyrażenia )is
1`.j
Przypadek następująco różne zasady pierwszeństwa, ponieważ,
ma najniższy priorytet operatora. Z powodu tych przepisów, kompilator widzi przypisania ekspresję Constant Constant ... . Wyrażenia są ponownie oceniane w kolejności od lewej do prawej, a ich skutki uboczne pozostają widoczne, dlatego teżj
jest5
wynikiemj = 5
.Co ciekawe,
int j = 5,4,3,2,1;
specyfikacja języka nie zezwala. Inicjator oczekuje zadanie ekspresję więc bezpośredni,
operator nie jest dozwolone.Mam nadzieję że to pomoże.
źródło