Понимание того, как printf ( "% d\n", ({int n; scanf ( "% d", & n); n * n;})); работает в C

Я наткнулся на эту программу через ответ quora

 #include<stdio.h>
 int main() {
    printf("%d\n", ( { int n; scanf("%d", &n); n*n; } ));
    return 0;
 }

Мне было интересно, как это работает, и если это соответствует стандарту?

Ответ 1

Этот код использует функцию "GNU C", называемую выражением оператора, в которой заключенный в скобки составной оператор может использоваться как выражение, тип и значение которого соответствуют результату последнего оператора в составной инструкции. Это не синтаксически допустимая C, а функция GCC (также принятая некоторыми другими компиляторами), которая была добавлена ​​предположительно потому, что она считалась важной для написания макросов, которые не оценивают свои аргументы более одного раза.

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

Ответ 2

Я не верю, что это сработает... n имеет локальную область в фигурных скобках... когда вы выходите из фигурных скобок, n становится undefined, хотя я полагаю, что может все еще существуют где-то в стеке и может работать. Он просил о проблемах внедрения, и я гарантирую, что это зависит от реализации.

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

Ответ 3

Это работает. Я не получаю никаких предупреждений от gcc, поэтому я полагаю, что он соответствует стандарту.

Магия - это замыкание:

{ int n; scanf("%d", &n); n*n; }

Этот самородок сканирует целое число с консоли (без проверки ошибок) и разбивает его на квадрат, возвращая квадрат числа. В древних реализациях C возвращается последнее число в стеке. n*n помещает номер в стек.

Это значение передается printf:

printf("%d\n", <scanned>);

Итак, чтобы ответить на ваши вопросы: Да, это работает. Да, это "стандарт" (в той степени, в которой кто-то полностью соответствует стандарту). Нет, это не очень хорошая практика. Это хороший пример того, что я, вызвав крик коленного сустава, называю "любовным письмом компилятора", разработанным в основном для того, чтобы показать, насколько умный программист, не обязательно решить проблему или быть эффективным.