2015-07-28 35 views
29

Widziałem to here i nie wiem, co to znaczy:Co znaczy & (int) {1} w C++?

&(int) { 1 } 

myślałem, że to dziwne, bo wydaje się, nieprawidłowej składni. Rzuca zakres bloków (?) Losowo 1 w środku (bez średnika) i zabiera adres. Nie ma dla mnie większego sensu. Czy możecie mnie oświecić?

próbowaliśmy go w/C++ 11, więc kompiluje:

auto a = &(int) { 1 }; 

Ale nie mam pojęcia, co robić ze zmienną.

+0

Dowolny kontekst, z którego pochodzi? Nie kompiluje się (http://ideone.com/hyQcy9) samodzielnie ... – yizzlez

+0

Wygląda jak [literał złożony] (http://stackoverflow.com/q/28116467/1708801), ale nie jest to pewne bez więcej kontekstu, bardziej prawdopodobne, że był to kod C, ponieważ jest on obsługiwany jako rozszerzenie w C++ i biorąc pod uwagę adres byłby to zły pomysł, ponieważ semantyczne są różne. –

+0

@awesomeyi Nie pamiętam. Często jest tak, że kod znaleziony w google nie kompiluje się tak czy inaczej. –

Odpowiedz

32

O ile mogę powiedzieć, że jest to compound literal, to cecha C99, to not standard C++ ale zarówno gcc i brzęk wsparcie to jako rozszerzenie:

ISO C99 obsługuje złożonych literałów. Dosłowny skład wygląda jak rzut zawierający inicjator. Jego wartość jest obiektem typu określonego w rzutowaniu, zawierającego elementy określone w inicjatorze; to jest l-wartość. Jako rozszerzenie GCC obsługuje literały złożone w trybie C90 i C++, chociaż semantyka jest nieco inna w C++.

Zazwyczaj podany typ jest strukturą. Załóżmy, że foo struct i struktura deklarowane są w następujący sposób:

struct foo {int a; char b[2];} structure; 

Oto przykład konstruowania foo struct ze związkiem dosłownym:

structure = ((struct foo) {x + y, 'a', 0}); 

Jest to równoważne formie pisemnej, co następuje:

{ 
    struct foo temp = {x + y, 'a', 0}; 
    struct 

w tym przypadku rodzaj a będzie wskaźnik do int. Mam nadzieję, że był to pierwotnie kod C, ponieważ zgodnie z dokumentem gcc:

W języku C literał złożony oznacza obiekt nienazwany ze statycznym lub automatycznym czasem przechowywania. W języku C++ dosłownym składnikiem jest tymczasowy obiekt, który żyje tylko do końca jego pełnej ekspresji.

i tak przyjmowanie adresu w C++ jest prawdopodobnie złym pomysłem, ponieważ czas życia obiektu kończy się na końcu pełnego wyrażenia. Chociaż mógł to być kod w C++, który opierał się na nieokreślonym zachowaniu.

Jest to jeden z tych przypadków, w których przy użyciu poprawnej flagi naprawdę bardzo pomaga, zarówno w gcc i brzękiem wykorzystaniem -pedantic przyniesie ostrzeżenie i błąd, na przykład gcc mówi:

warning: ISO C++ forbids compound-literals [-Wpedantic] 
auto a = &(int) { 1 }; 
        ^
error: taking address of temporary [-fpermissive] 

jeśli używamy -fpermissive to gcc, to rzeczywiście pozwala na kompilowanie tego kodu. Nie mogę zdobyć się na budowanie tego kodu z flagami we współczesnych wersjach, chociaż stare wersje wydają się zezwalać na to przy użyciu -Wno-address-of-temporary. Zastanawiam się, czy gcc pozwala na to jako remnant of an old extension.

Uwaga, pytanie Cryptic struct definition in C ma dość ciekawe (zależności od definicji interesującej) użycie literałów złożonych.

Zakładając Schizmę is correct i this question jest oryginalne źródło, to zastosowanie w tym kodzie w przykładzie:

if (setsockopt(server_connection.socket, SOL_SOCKET, SO_REUSEADDR, &(int) { 1 }, sizeof(int)) < 0) { 

jest ważne zastosowanie zarówno w C99 i C++.

5

Nie jest to od razu oczywiste, ale jeśli spojrzysz na otaczający kod, stanie się jasne, do czego służy i jakie ma być.

Przyjmuje adres tymczasowej anonimowej struktury zawierającej pojedynczą anonimową liczbę całkowitą, która jest inicjowana przez inicjator oznaczony jako C99. Powodem jest, że setsockopt nie chce liczby całkowitej, ale wskaźnik do niej (lub raczej wskaźnik do coś, a rozmiar coś).

Innymi słowy, jest to bardzo fajny hack, który dostarcza rodzaj liczby całkowitej (bez wyraźnej zmiennej tymczasowej) do funkcji, która oczekuje wskaźnika.

Tak, to jest funkcjonalnie identyczne:

int blah = 1; 
setsockopt(..., &blah, ...); 

... oprócz tego, że działa bez wprowadzania blah.

+0

Jestem trochę nieufny, zakładając, że odniesienie jest tym samym, o którym mowa w PO ... Schism sugeruje w komentarzu, skąd pochodzi, ale OP nie potwierdził jeszcze. Link został dodany przez innego użytkownika, a nie OP. –

+0

@ShafikYaghmour: Ah, nie zauważyłem, że komentarz nie pochodzi z PO, pomyślałem, że tak. – Damon