Що це за синтаксис C ++, який поміщає блок, оточений фігурними дужками, де очікується вираз?


78

Я натрапив на цю дивну програму на C ++.

#include <iostream>
using namespace std;
int main()
{
  int a = ({int x; cin >> x; x;});
  cout << a;
}

Хто-небудь може пояснити, що відбувається? Як називається ця конструкція?


51
це називається "заплутати код"
BЈовић

2
@VJo: Я маю на увазі, як називається ця конструкція "({})"? Це схоже на анонімні функції?
Кошиміцу

1
+1 Блімі, я ніколи раніше цього не бачив. Шкода, що це специфічно для GNU C / C ++ ...
sehe

1
+1, мало схожий на лямбда-функцію :)
iammilind

18
Це лише я, або в gcc є більше химерних нестандартних розширень, ніж у будь-якому іншому компіляторі?
Девід Хеффернан

Відповіді:


68

Він присвоює користувачеві введене значення aта друкує його. це робиться за допомогою Statement Expression.

Вирази виразів - розширення компілятора gnu gcc не підтримуються стандартами C / C ++. Отже, будь-який код, який використовує вираз оператора, нестандартно відповідає та не переноситься.

IBM IBM XL C / C ++ v7.0 також підтримує вирази висловлювань, і їх документація влучно пояснює їх:

Вирази заяви:

Складений вираз - це послідовність висловлювань, укладених фігурними дужками. У GNU C складений вираз усередині дужок може виглядати як вираз у тому, що називається a Statement expression.

         .--------------.
         V              |
>>-(--{----statement--;-+--}--)--------------------------------><

Значення виразу оператора - це значення останнього простого виразу, що відображається у всій конструкції. Якщо останнє твердження не є виразом, тоді конструкція має тип void і не має значення.

Завжди скомпілювати код, вибравши sandard в GCC, використовуйте один з варіантів -ansi, -std=c90або -std=iso9899:1990, -std=c++03, -std=c++0x; щоб отримати всю діагностику, яку вимагає стандарт, слід також вказати -pedantic(або -pedantic-errorsякщо ви хочете, щоб це були помилки, а не попередження)


56

Це розширення GCC. Складіть свій код з -pedanticпрапором , якщо ви хочете , щоб позбутися від речей , як це (і ви дійсно дійсно хочете).


10
Я підозрюю, що набрав стільки голосів, тому що багато людей отримали полегшення, дізнавшись, що те, про що вони не чули чи використовували, і так не є стандартним.
Благовест Буюклієв

18

Він створює вбудований обсяг, оголошує xвсередині нього, зчитує його зі стандартного вводу, і весь висновок нарешті обчислюється на x, якому присвоюється a.

Оператор-кома працює аналогічно, хоча для цього не потрібна окрема область. Наприклад:

int x;
int a = (cin >> x, x);

зробив би те саме. Всі оператори, пов'язані з комами, будуть виконуватися послідовно, а результат усього виразу буде встановлений на значення самого правого операнда.


Чи існує якась конкретна назва "({})"?
Кошиміцу

@Koshimitsu: Ні, бо це комбінація операторів (якщо ви хочете їх так назвати). Фігурні дужки {} визначають початок ({) і кінець (}) області в даному випадку. Звичайні дужки просто там, щоб інкапсулювати визначення області дії та повернене значення. Я не зовсім впевнений у тому, чи можна в цьому випадку опустити ці звичайні дужки, проте, я сподівався б, що вони можуть.
Rycul

1
@Koshimitsu: Я не дуже знайомий з C ++, але в C це абсолютно законно, і я використовував його багато разів.
Благовест Буюклієв

1
@Neil: ну, можливо, це тому, що gcc - єдиний компілятор, яким я користуюся, отже, я ввів в оману.
Благовест Буюклієв

13

Я не вірю, що це стандартний C ++. Ймовірно, це розширення, специфічне для компілятора, яке дозволяє внутрішній обсяг оцінити значення.


1
@Doc: Нісенітниця. Для початку це не стандарт C. Можливо, його було додано до C ++ 0x, я не знаю.
Олівер Чарльзворт,

13
@Doc ви помиляєтесь. Це не стандартний C ++ і не стандартний C. Це розширення GCC, яке називається "вираз оператора".
Йоханнес Шауб - літб

Я не вірю, що це так. Visual Studio цього точно не прийме.
Щеня,

3
@mathepic: Очевидно, ні GCC (без правильних варіантів), отже, питання і плутанина тут ...
rubenvb
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.