Que signifie &(int) {1} en C++?

j'ai vu ce ici et je ne sais pas ce que ça veut dire:

&(int) { 1 }

j'ai trouvé ça bizarre parce que ça ressemble à une syntaxe non valide. Il lance un scope de bloc(?) avec un 1 aléatoire au milieu (sans point-virgule) et en prenant l'adresse. Ne fait pas beaucoup de sens pour moi. Pourriez-vous les gars m'éclairer?

a essayé w / C++11, donc il compile:

auto a = &(int) { 1 };

mais je ne sais pas quoi faire faire avec la variable.

29
demandé sur Community 2015-07-28 05:04:51

2 réponses

autant que je puisse dire c'est un composé littéral , il est caractéristique C99, il est pas standard c++ mais gcc et clang le supportent comme une extension:

ISO C99 support compound literals. Un composé littéral ressemble à un moulage contenant un initialiseur. Sa valeur est un objet du type spécifié dans le casting, contenant les éléments spécifiés dans le initialiseur; c'est une lvalue. Comme un extension, GCC prend en charge les littérales composées en mode C90 et en C++, bien que la sémantique soit quelque peu différente en C++.

habituellement, le type spécifié est une structure. Supposons que struct foo et FOO structure sont déclarés comme suit:

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

voici un exemple de construction d'une structure foo avec un composé littéralement:

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

cela équivaut à écrire ce qui suit:

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

dans ce cas, le type de a pointerait vers int. Avec un peu de chance, il s'agissait à l'origine du code C car comme le dit le document gcc:

en C, Un composé littéral désigne un objet sans nom avec une durée de stockage statique ou automatique. En C++, Un composé littéral désigne un objet temporaire, qui ne vit que jusqu'à la fin de sa pleine expression.

et donc prendre l'adresse en C++ est probablement une mauvaise idée car la durée de vie de l'objet est à la fin de l'expression. Bien que, il aurait pu être le code C++ qui s'est appuyé sur un comportement non défini.

C'est l'un de ces cas où l'utilisation des bons drapeaux aide vraiment beaucoup, à la fois dans gcc et clang en utilisant -pedantic produira un avertissement et une erreur, par exemple gcc dit:

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

si nous utilisons -fpermissive est gcc il fait en effet permettez à ce code de se compiler. Je ne peux pas obtenir clang pour construire ce code avec des drapeaux dans les versions modernes bien que les anciennes versions semblent l'autoriser en utilisant -Wno-address-of-temporary . Je me demande si gcc autorise cela comme un vestige d'une ancienne extension .

Note, la question Cryptic struct definition in C a un assez intéressant ( dépendant de votre définition d'intéressant ) utilisation de la littérature composée.

supposant schisme est correct et cette question est la source originale puis l'utilisation dans ce code dans l'exemple:

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

est une utilisation valide en C99 et C++.

32
répondu Shafik Yaghmour 2017-05-23 11:54:12

Il n'est pas immédiatement évident, mais si vous regardez le code environnant, il devient clair qu'il est utilisé pour, et ce qu'il a à être.

il prend l'adresse d'une structure anonyme temporaire contenant un seul entier anonyme qui est initialisé via un initialiseur désigné C99. La raison est que setsockopt ne veut pas un entier, mais un pointeur vers lui (ou plutôt, un pointeur vers quelque chose , et la taille du quelque chose).

en d'autres termes, c'est un hack très cool pour fournir une sorte d'argument entier (sans variable temp explicite) à une fonction qui attend un pointeur.

donc, c'est fonctionnellement identique à:

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

... sauf qu'il fonctionne sans introduire blah .

5
répondu Damon 2015-08-03 13:19:13