Je suis tombé sur ce programme C++ bizarre.
#include <iostream>
using namespace std;
int main()
{
int a = ({int x; cin >> x; x;});
cout << a;
}
Quelqu'un peut-il expliquer ce qui se passe ? Comment s'appelle cette construction ?
Je suis tombé sur ce programme C++ bizarre.
#include <iostream>
using namespace std;
int main()
{
int a = ({int x; cin >> x; x;});
cout << a;
}
Quelqu'un peut-il expliquer ce qui se passe ? Comment s'appelle cette construction ?
Il affecte la valeur de l'entrée de l'utilisateur à a
et l'imprime. Pour ce faire, il faut utiliser un fichier Statement Expression
.
Les expressions de déclaration sont un extension du compilateur gnu gcc et ne sont pas pris en charge par les normes C/C++. Par conséquent, tout code qui utilise l'expression de déclaration n'est pas conforme aux normes et n'est pas portable.
La version 7.0 d'IBM XL C/C++ prend également en charge les expressions de déclaration et sa documentation les explique de manière appropriée :
Expressions de déclarations :
Une instruction composée est une séquence d'instructions entourées d'accolades. En GNU C, une instruction composée entre parenthèses peut apparaître comme une expression dans ce que l'on appelle un fichier
Statement expression
.
.--------------.
V |
>>-(--{----statement--;-+--}--)--------------------------------><
La valeur d'une expression de déclaration est la valeur de la dernière expression simple apparaissant dans la construction entière. Si la dernière déclaration n'est pas une expression, alors la construction est de type void et n'a pas de valeur.
Compilez toujours votre code en sélectionnant un standard dans GCC : utilisez l'une des options suivantes -ansi
, -std=c90
o -std=iso9899:1990
, -std=c++03
, -std=c++0x
; pour obtenir tous les diagnostics requis par la norme, il faut également préciser -pedantic
(ou -pedantic-errors
si vous voulez qu'ils soient des erreurs plutôt que des avertissements).
Il crée une portée en ligne, déclare x
à l'intérieur, le lit à partir de l'entrée standard et l'ensemble de l'instruction est finalement évalué à x
qui est affecté à a
.
L'opérateur virgule fonctionne de manière similaire, bien qu'il ne nécessite pas de portée séparée. Par exemple :
int x;
int a = (cin >> x, x);
ferait la même chose. Toutes les instructions reliées par des virgules seront exécutées séquentiellement, et le résultat de l'expression entière sera fixé à la valeur de l'opérande le plus à droite.
@Koshimitsu : Il n'y en a pas, car c'est une combinaison d'opérateurs (si vous voulez les appeler ainsi). Les accolades {} définissent le début ({) et la fin (}) d'une portée dans ce cas. Les parenthèses normales sont juste là pour encapsuler la définition et la valeur de retour de l'étendue. Je ne suis pas tout à fait sûr que ces crochets réguliers puissent être omis dans ce cas, mais je pense que oui.
Koshimitsu : Je ne suis pas très familier avec le C++, mais en C c'est parfaitement légal, et je l'ai utilisé de nombreuses fois.
@Doc : N'importe quoi. Ce n'est pas du C standard, pour commencer. Cela a peut-être été ajouté à C++0x, je ne sais pas.
@Doc vous vous trompez. Ce n'est pas du C++ standard ni du C standard. C'est une extension de GCC appelée "expression de déclaration".
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
2 votes
@VJo : Je veux dire, comment s'appelle cette construction "({})" ? Est-il similaire aux fonctions anonymes ?
1 votes
+1 Blimey, j'avais jamais J'ai déjà vu ça auparavant. Dommage que ce soit spécifique à GNU C/C++...
1 votes
+1, ressemble un peu à la fonction lambda :)
18 votes
C'est moi ou il y a plus d'extensions bizarres non standard dans gcc que dans n'importe quel autre compilateur ?
1 votes
David Ouais, c'est plein à craquer de b*ggers. C'est ce qui rend l'utilisation de -pedantic presque essentielle.
0 votes
Suppression de la méta-tag superflue.
0 votes
C'est un mode d'écriture non portable :
int main() { int a; cin >> a; cout << a; }
. Je suppose qu'il s'agit d'un exemple réduit au minimum ; il n'y a aucun intérêt à utiliser le mécanisme dans ce contexte, alors qu'il pourrait être utilisé dans d'autres contextes plus larges.