Właśnie natknąć się kod, który zasadniczo wykonuje następujące operacje:Co oznacza lista wartości oddzielonych przecinkami, ujęta w nawias w C? a = (1, 2, 3);
int a = (1, 2, 3);
Nigdy nie widziałem tej notacji wcześniej. Co to znaczy?
Właśnie natknąć się kod, który zasadniczo wykonuje następujące operacje:Co oznacza lista wartości oddzielonych przecinkami, ujęta w nawias w C? a = (1, 2, 3);
int a = (1, 2, 3);
Nigdy nie widziałem tej notacji wcześniej. Co to znaczy?
to comma operator: ocena a, b
najpierw podlega ocenie a
, następnie b
, a wynikiem jest b
.
int a = (1, 2, 3);
ocenia najpierw 1
, następnie 2
wreszcie 3
i wykorzystuje ten ostatni 3
do zainicjowania a
. Jest to bezużyteczne, ale może być użyteczne, gdy lewy operand z ,
ma efekty uboczne (zwykle: gdy jest to wywołanie funkcji).
Zazwyczaj piszę to jak '({doSomething(); x;})', co jest szczególnie przydatne w przypadku definicji makr, które działają z tymczasowymi rezultatami. Czy istnieje jakaś różnica między tymi oznaczeniami, poza faktem, że używam średnika zamiast przecinka, aby oddzielić te (pod) wyrażenia? – leemes
@leemes Jest to nieważne w standardowym C i C++, ale jest akceptowane przez niektóre kompilatory (przynajmniej GCC) jako rozszerzenie pozwalające na używanie instrukcji, a nie tylko na wyrażenia, dzięki czemu możesz zrobić '({if (0) {1;} 2;}) '. – hvd
"zwykle: kiedy jest to wywołanie funkcji" czy możesz to wyjaśnić? Pytam, ponieważ nie rozumiem kontekstu. masz na myśli foo (T, T2), ten przecinek lub foo (T), foo (T)? –
encyklopedia: Comma operator
i = (a, b, c); // stores c into i
Wykorzystuje comma operator, który to ocenia każdą kolejno ekspresji operandu (wprowadzenie właściwej sekwencji wskazuje pomiędzy nimi) i zwraca ostatni. Zatem twój przykład jest faktycznie równoważny z int a = 3;
.
Ale to jest rzeczywiście jednym z najmniej wykorzystywanych operatorów C i C++ i nie należy mylić z przecinkami wyrażeń użytych w wywołaniu funkcji list inicjująca i wszystkich innych miejscach. Niezbyt rzadkim przypadkiem użycia byłoby wielokrotne zwiększenie liczby pętli (for(...; ...; ++i,++j)
), mimo że prawdopodobnie nigdy nie myślałeś o tym używając tak zwanego operatora przecinka.
Kolejny problem polegający na interwencji jest próbą umieszczenia wielu konceptualnie powiązanych wyrażeń w pojedynczym komunikacie (np. Zwrot) ze względu na jasność i zwięzłość, tak jak w przypadku implementacji starego dobrego frexp
z argumentem zwracającym dziwny wskaźnik (ignorować faktu, że właściwa C++ po prostu wrócić parę):
double frexp(double arg, int *exp)
{
if(...)
return *exp=..., result;
...
}
który jest o wiele bardziej efektywna niż równowartość
double frexp(double arg, int *exp)
{
if(...)
{
*exp = ...;
return result;
}
...
}
Podoba mi się ta odpowiedź lepiej niż obecnie najlepiej głosowana przez hvd, ale kim jestem, aby dyskutować z Internetem? ':)' –
@ ChristianRau zapamiętaj [to] (http://stackoverflow.com/questions/16538458/how-to-make-ix-works-as-i/16538741#16538741), możesz to zrobić, używając przecinka tutaj i pokaż przykład :-) –
@Koushik Hah, racja! Nadal dziwne, ale lepsze od wersji '?:'. Wciąż jednak nie pokażę tego w tej odpowiedzi, ponieważ tak naprawdę nie jest to rozsądny przypadek użycia. Ale +1 dla wzajemnego powiązania. –
Wylicza tylko 1, 2 i 3 (ponieważ są to tylko wartości, ale równie dobrze mogą być wywołania funkcji) i ustawia wartość (lub wartość zwracaną) ostatniej wartości na lewy operand (w twoim przykładzie, za).
Może to pomoże Ci zrozumieć, jak to dział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);
}
wyjściowa:
toto()
tata()
42
Edit: kod THA C, działa tak samo w C++
Wziąłem wolność, aby dodać odpowiednie wyjście. –
Jest operator przecinek . Standard C11 mówi o jednym przypadku użycia tego rodzaju operatora.
C11 standard 6: 5: 17
przecinek operatora
Lewa argumentu operatora przecinek oceniano jako pusta ekspresji; istnieje punkt sekwencji między jego oceną a tym prawego argumentu. Następnie prawy operand jest oceniany; wynik ma swój typ i value.114)
Operator przecinka (w sposób opisany w niniejszym podrozdziale ) nie może pojawić się w kontekstach, gdzie przecinek jest używany do odrębne pozycje na liście (na przykład jako argumenty funkcji lub list z inicjalizatorów ). Z drugiej strony, może być stosowany w nawiasach w postaci lub w drugim wyrażeniu operatora warunkowego w takich kontekstach. W wywołaniu funkcji f (a, (t = 3, t + 2), c), funkcja posiada trzy parametry, z których druga ma wartość 5.
To comma operator . "Owija" wiele wyrażeń, ocenia je od lewej do prawej, a wartość całego wyrażenia jest określana przez ostatnie podekspresję. W twoim przykładzie wartość ta wynosi 3
.
Sytuacja, w której szczególnie przydatny jest operator przecinka, polega na tym, że chcesz wykonać wiele czynności w wyrażeniu "inkrementacja" pętli for, na przykład aby zwiększyć dwóch zmiennych.
Przykład: Iteracja obrazu wzdłuż przekątnej, przy użyciu x
i y
jako oddzielnych zmiennych. Używam dwóch oddzielnych zmiennych dla x
i y
, ponieważ mógłbym zmienić jeden z nich w pętli niezależnie od drugiego (pamiętaj, to tylko głupi przykład). Więc chcę, aby zwiększyć zarówno x
i y
w „przyrost” Oświadczenie dla pętli:
for(int x = 0, y = 0; x < width && y < height; ++x, ++y) {
// ... ^^^^^^^^
}
Zauważ, że „inicjalizacji” wyrazem dla pętli robi nie użyć operatora przecinek; to po prostu deklaruje dwie zmienne.
Wolałbym zmienić * "separator" * na * "operator" * w pierwszym zdaniu, ponieważ ten pierwszy byłby raczej tym, co nazywam zwykłym (bez operatora) użyciem przecinków. Ale dobrze, że wskazałeś różnicę do wyrażenia inicjalizacji pętli for. –
Ups, to było przez przypadek. Dzięki za wskazanie;) – leemes
marnowanie wpisanego kodu, który jest. 3 jest przypisane do a. –
Zastanawiam się jednak, kiedy ktoś wykopuje dla tego duplikat (ponieważ nie mogę uwierzyć, że nie ma żadnego). –
@ ChristianRau, jest bardzo prawdopodobne, że istnieje - ale ja naprawdę walczyłem o skonstruowanie zapytania w google i StackOverflow, które zwróciło znaczące wyniki, ponieważ nie znam nazwy operatora! –