Вызов функции C без скобки - PullRequest
0 голосов
/ 19 мая 2018

Вот простая программа на C:

#include <stdio.h>

int main(void)
{
    printf("Display something\n");
    fflush stdout;
    return 0;
}

Скомпилирована с msys2 mingw-w64 gcc версии 7.3.0 и опцией -Wall и все работает нормально, как если бы 5-я строка была fflush(stdout);.

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

src/main.c: In function 'int main(int, char**)':
src/main.c:5:18: error: expected ';' before 'parameter'
  custom_function parameter;
                  ^~~~~~~~~

Итак, что происходит с функцией fflush?Может кто-нибудь объяснить мне?Есть ли у вас такое же поведение с другими компиляторами C?

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

Ваш вопрос:

enter image description here

См. Ответ Жан-Франсуа Фабра.в стандарте есть странность (и я не утверждаю, что это нечто большее).

C99 7.19.1 гласит:

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

...

Макросы:

...

stderr stdin stdout

, которые являются выражениями типа "указатель на FILE", которые указывают на объекты FILE, связанные, соответственно, со стандартной ошибкой, входным и выходным потоками.

Как давно сказал Кит Томпсонназад В контексте это говорит о том, что они являются макросами, но в описании всех других макросов используется фраза «которая расширяется до».Для stderr, stdin и stdout говорится, что они являются выражениями (что, если они являются макросами, не совсем корректно).

Если им разрешено быть, скажем,, объявляя объекты, а не макросы, следует изменить 7.19.1p1, чтобы разрешить эти объявления, и описание stderr, stdin и stdout не должно быть частью длинного предложения на странице.

Более правдоподобно, если они являются обязательными для использования в качестве макросов, фразу «которые являются выражениями» следует заменить на «которые расширяют до выражений».

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

0 голосов
/ 19 мая 2018

Давайте посмотрим на вывод препроцессора (используя MinGW и gcc -E test.c командную строку):

   fflush 
# 5 "test.c" 3
          (&(* _imp___iob)[1])
# 5 "test.c"
                ;

, как вы видите stdout - это макрос, который расширяется до (&(* _imp___iob)[1]) со скобками.

так что компилятор использует эти скобки и синтаксис в порядке.

Но это только из-за магии макроса и того факта, что большинство макросов защищены скобками, чтобы избежать побочных эффектов с другими токенами (приоритет оператора дляпример)

Вы можете воспроизвести это без каких-либо включений с помощью этого простого кода:

#define arg ("hello")

void f(const char *x)
{
}

int main(int argc, char** argv)
{
    f arg;
    return 0;
}

Конечно, это плохая практика, сбивает с толку IDE (и людей), поэтому просто не делайте этого.

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