Как оценивается это утверждение и как это называется? - PullRequest
9 голосов
/ 17 июня 2011
#define FOO(val) \
({                                              \
   int b = val;                                 \
   printf("First, let's count to %d\n", val);   \
   for (int i = 1; i <= val; i++) {             \
      printf("%d...\n", i);                     \
   }                                            \
   b++;                                         \
   b;                                           \
})

int main() {
   int a = FOO(6);
   printf("a=%d\n", a);

   a = (4);     // straightforward, everyone should be familiar with this
   a = (4;);    // does not compile
   a = { 4; };  // does not compile
   a = ({ 4;}); // valid, a will equal 4


   return 0;
}

Я пытаюсь обернуть голову вокруг приведенного выше примера.Как и почему работает макрос FOO (последний оператор действует как возвращаемое значение)?Что касается синтаксиса, как называются отдельные части и какие другие правила применяются?

Ответы [ 4 ]

7 голосов
/ 17 июня 2011

Используется нестандартное расширение GCC, чтобы разрешить возврат значений из блоков кода, в основном предназначенных для макросов. Последнее значение внутри блока кода обрабатывается как «возвращаемое значение».

Ярким примером того, почему это было необходимо, является обычный макрос max:

#define max(a,b) (a)<(b)?(b):(a)

Вызов max(new A(), new B()) приводит к выделению 3 объектов, тогда как на самом деле вы хотите только 2 (надуманный пример, но суть , один из операндов оценивается дважды ).

С этим расширением вы можете вместо этого написать:

#define max(a,b) ({ typeof(a) _a=(a); typeof(b) _b=(b); _a<_b?_b:_a; })

В этом случае оба операнда вычисляются ровно один раз, точно так же, как функция, но со всеми преимуществами макросов (какими они являются).

4 голосов
/ 17 июня 2011

Это расширение GCC, называемое выражениями операторов .

Один совет:

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

Например, я скомпилировал его с опцией -pedantic, и там написано:

предупреждение: ISO C ++ запрещает использование фигурных скобок в выражениях

4 голосов
/ 17 июня 2011

Это называется операторным выражением и не является частью стандартного ISO, однако GCC поддерживает его.

Цитата из руководства:

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

...

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

0 голосов
/ 17 июня 2011

Я почти уверен, что это недопустимый C ++.Глава 5 стандарта C ++ определяет, что такое выражение .FOO(val) уверен, что, черт возьми, это не выражение в соответствии с этим.Следовательно, int a = FOO(6); недействительно

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