Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C function call without bracket

Tags:

c

function

mingw

Here is a simple C program:

#include <stdio.h>

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

Compiled with msys2 mingw-w64 gcc version 7.3.0 and option -Wall and everything works fine, just as if the 5th line was fflush(stdout);.

I tried to reproduce such a call with my own function, but I get the perfectly expected error

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

So, what happens with the fflush function? Can somebody explain me? Do you have the same behavior with other C compilers?

like image 716
GholGoth21 Avatar asked May 19 '18 19:05

GholGoth21


People also ask

Can you call a function without parentheses?

When we call a function with parentheses, the function gets execute and returns the result to the callable. In another case, when we call a function without parentheses, a function reference is sent to the callable rather than executing the function itself.

Can I call a function without parameter?

You can use a default argument in Python if you wish to call your function without passing parameters. The function parameter takes the default value if the parameter is not supplied during the function call.

What does call () do in C?

The call by reference method of passing arguments to a function copies the address of an argument into the formal parameter. Inside the function, the address is used to access the actual argument used in the call. It means the changes made to the parameter affect the passed argument.


2 Answers

Your question:

enter image description here

See Jean-François Fabre's answer. there's an oddity in the wording in the standard (and I make no claim that it's anything more than that).

C99 7.19.1 says:

The header declares three types, several macros, and many functions for performing input and output.

...

The macros are

...

stderr stdin stdout

which are expressions of type "pointer to FILE" that point to the FILE objects associated, respectively, with the standard error, input, and output streams.

As Keith Thompson have said long ago In context, this says they're macros -- but the descriptions of all the other macros use the phrase "which expands to". For stderr, stdin, and stdout, it says they are expressions (which, if they're macros, isn't strictly correct).

If they're allowed to be, say, declared objects rather than macros, then 7.19.1p1 should be changed to allow for these declarations, and the description of stderr, stdin, and stdout shouldn't be part of the page-long run-on sentence.

More plausibly, if they are required to be macros, the phrase "which are expressions" should be changed to "which expand to expressions".

They are not guaranteed to be macros. In your case though, you got lucky the macro expands to an expression with protection brackets. A sheer example of evil macro hiding the actual content.

like image 113
Imobilis Avatar answered Oct 26 '22 23:10

Imobilis


Let's see preprocessor output (using MinGW, and gcc -E test.c command line):

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

as you see stdout is a macro which expands to (&(* _imp___iob)[1]) with parentheses.

so the compiler uses those parentheses and the syntax is okay.

But that's only because of macro magic, and the fact that most macros are protected by parentheses to avoid side-effects with other tokens (operator precendence for instance)

You can reproduce that without any includes with this simple code:

#define arg ("hello")

void f(const char *x)
{
}

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

Of course this is bad practice, confuses IDEs (and humans), so just don't do it.

like image 35
Jean-François Fabre Avatar answered Oct 26 '22 23:10

Jean-François Fabre