Что это за синтаксис C , который помещает окруженный фигурными скобками блок туда, где ожидается выражение?

#c #syntax #language-extension #gcc-extensions #gcc-statement-expression

#c #синтаксис #языковое расширение #gcc-extensions #gcc-statement-выражение

Вопрос:

Я наткнулся на эту странную программу на C .

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

Кто-нибудь может объяснить, что происходит? Как называется эта конструкция?

Комментарии:

1. @VJo: Я имею в виду, как называется эта конструкция «({})»? Похоже ли это на анонимные функции?

2. 1 Черт возьми, я никогда этого раньше не видел. Жаль, что он специфичен для GNU C / C …

3. 1, немного похоже на лямбда-функцию 🙂

4. Мне только кажется, или в gcc больше странных нестандартных расширений, чем в любом другом компиляторе?

5. @David Да, он битком набит идиотами. Это то, что делает использование -pedantic почти необходимым.

Ответ №1:

Он присваивает введенное пользователем значение a и распечатывает его. это делается с помощью Statement Expression .

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

IBM XL C / C версии 7.0 также поддерживает выражения операторов, и в его документации они подробно объясняются:

Выражения операторов:

Составной оператор — это последовательность операторов, заключенных в фигурные скобки. В GNU C составной оператор внутри круглых скобок может отображаться как выражение в том, что называется Statement expression .

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

Значение выражения оператора — это значение последнего простого выражения, которое появляется во всей конструкции. Если последний оператор не является выражением, то конструкция имеет тип void и не имеет значения.

Всегда компилируйте свой код, выбирая стандарт в GCC: используйте один из вариантов -ansi , -std=c90 или -std=iso9899:1990 , -std=c 03 -std=c 0x ; чтобы получить всю диагностику, требуемую стандартом, вам также следует указать -pedantic (или -pedantic-errors , если вы хотите, чтобы это были ошибки, а не предупреждения).

Ответ №2:

Это расширение GCC. Скомпилируйте свой код с -pedantic флагом, если вы хотите избавиться от подобных вещей (и вы действительно этого хотите).

Комментарии:

1. Я подозреваю, что это получило так много голосов, потому что многие люди почувствовали облегчение, узнав, что то, о чем они не слышали или не использовали, в любом случае не является стандартным.

Ответ №3:

Он создает встроенную область видимости, объявляет x внутри нее, считывает ее из стандартного ввода, и весь оператор, наконец, вычисляется в x , который присваивается a .

Оператор запятой работает аналогично, хотя для этого не требуется отдельная область видимости. Например:

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

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

Комментарии:

1. Существует ли какое-либо конкретное имя для «({})»?

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

3. @Koshimitsu: Я не очень хорошо знаком с C , но в C это совершенно законно, и я использовал это много раз.

4. @Neil: ну, может быть, это потому, что gcc — единственный компилятор C, который я использую, поэтому я был введен в заблуждение.

Ответ №4:

Я не верю, что это стандартный C . Вероятно, это специфичное для компилятора расширение, которое позволяет внутренней области вычислять значение.