В каких версиях C блок внутри скобки используется для возврата допустимого значения? - PullRequest
17 голосов
/ 28 октября 2009

Если я сделаю:

int j = ({int x = 7; x+3;});

В i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (сборка Apple Inc., сборка 5646) gcc компилируется просто отлично. Рассматриваемый блок ({int x = 7; x+3;}) возвращает значение последнего оператора в качестве значения блока. Если вы удалите скобки, он не скомпилируется. Могу ли я ожидать, что это будет работать в большинстве компиляторов Си?

Кроме того, как называется эта конструкция? У меня было много проблем с поиском, потому что поисковые системы не индексируют () или {}, а C - ужасный поисковый термин. Я также не смог найти ничего об этом ни в одной из своих книг, возможно, потому что я не знаю, что искать.

Ответы [ 3 ]

31 голосов
/ 28 октября 2009

Это расширение GCC :

Составной оператор, заключенный в скобки, может отображаться как выражение в GNU C. Это позволяет вам использовать внутри выражения циклы, переключатели и локальные переменные.

Напомним, что составной оператор представляет собой последовательность операторов, заключенную в фигурные скобки; в этой конструкции круглые скобки идут вокруг скобок. Например:

 ({ int y = foo (); int z;
    if (y > 0) z = y;
    else z = - y;
    z; })

является допустимым (хотя и немного более сложным, чем необходимо) выражением для абсолютного значения foo ().

Последним в составном операторе должно быть выражение, за которым следует точка с запятой; значение этого подвыражения служит значением всей конструкции. (Если вы используете какой-то другой вид оператора последним в фигурных скобках, конструкция имеет тип void и, следовательно, фактически не имеет значения.) ...

7 голосов
/ 28 октября 2009

Если вы удалите скобку, она не скомпилируется.

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

6.7.8 Инициализация

11 Инициализатор для скаляра должен быть одним выражением, необязательно заключенным в фигурные скобки. начальное значение объекта - это значение выражения (после преобразования); того же типа применяются ограничения и преобразования как для простого присваивания, принимая тип скаляра быть безоговорочной версией объявленного типа.

6.2.5 Типы

21 Арифметические типы и типы указателей вместе называются скалярными типами. Массив и Типы структур вместе называются агрегатными типами.


Можно ли ожидать, что это будет работать в большинстве компиляторов c?

Нет. Выглядит как нестандартное расширение GNU.

Кроме того, как называется эта конструкция?

Интересно, а есть ли? На самом деле, это похоже на то, что обычно делают макросы.

7 голосов
/ 28 октября 2009

Можно ожидать, что он будет работать в большинстве версий GCC.

Вы можете ожидать, что он будет работать почти нигде - это расширение GCC.

Раздел руководства GCC, в котором описывается функция, называется «Заявления и объявления в выражениях»:

Составной оператор, заключенный в скобки, может отображаться как выражение в GNU C.

Позже это говорит:

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

Таким образом, «выражение оператора» представляется именем, используемым в документации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...