В каких версиях C есть блок внутри скобок, используемый для возврата значения?
Если я это сделаю:
int j = ({int x = 7; x+3;});
В i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5646) gcc компилируется просто отлично. Этот блок ({int x = 7; x+3;})
возвращает значение последнего оператора как значение блока. Если вы удалите скобку, она не компилируется. Могу ли я ожидать, что это будет работать в большинстве компиляторов C?
Кроме того, какое имя для этой конструкции? У меня было много проблем в поиске, потому что поисковые системы не индексируют ()
или {}
, а C - ужасный поисковый запрос. Я также не смог найти ничего об этом в любой из моих книг, возможно, потому, что я не знаю, что искать.
Ответы
Ответ 1
Если вы удалите скобку, она не компилируется.
Без круглых скобок компилятор будет рассматривать это как блок агрегатной инициализации и сработает, когда увидит ключевое слово int
. Вы не можете использовать ключевые слова в блоках инициализации.
6.7.8 Инициализация
11 Инициализатор для скаляра должен быть единственным выражением, необязательно заключенным в фигурные скобки. начальное значение объекта - это выражение (после преобразования); тот же тип ограничения и преобразования, как для простого присваивания, принимая тип скаляра быть неквалифицированной версией его объявленного типа.
6.2.5 Типы
21 Арифметические типы и типы указателей в совокупности называются скалярными типами. Массив и типы структуры совместно называются агрегатными типами.
Можно ли ожидать, что это будет работать в большинстве компиляторов c?
Нет. Похоже на нестандартное расширение GNU.
Кроме того, какое имя для этой конструкции?
Интересно, есть ли какие-то. Собственно, это похоже на то, что обычно делают макросы.
Ответ 2
Это aa расширение GCC:
Составной оператор, заключенный в круглые скобки, может отображаться как выражение в GNU C. Это позволяет использовать в выражении циклы, переключатели и локальные переменные.
Напомним, что составной оператор представляет собой последовательность утверждений, окруженных фигурными скобками; в этой конструкции круглые скобки охватывают фигурные скобки. Например:
({ int y = foo (); int z;
if (y > 0) z = y;
else z = - y;
z; })
является действительным (хотя и немного более сложным, чем необходимо) выражением для абсолютного значения foo ()
.
Последнее в составном выражении должно быть выражением, за которым следует точка с запятой; значение этого подвыражения служит значением всей конструкции. (Если вы используете какой-то другой оператор, последний в фигурных скобках, у конструкции есть тип void
и, следовательно, фактически нет значения.)...
Ответ 3
Вы можете ожидать, что он будет работать в большинстве версий GCC.
Вы можете ожидать, что он будет работать почти нигде - это расширение GCC.
Раздел руководства GCC, описывающий эту функцию, называется "Выражения и объявления в выражениях":
Составной оператор, заключенный в круглые скобки, может отображаться как выражение в GNU C.
Позже он говорит:
Любые временные числа, созданные в выражении оператора в выражении оператора, будут уничтожены на конец заявлений. Это делает выражения выражения внутри макросов слегка отличается от вызовов функций.
Итак, выражение "выражение" похоже на имя, используемое в документации.