5

This question is an offshoot of `f(void)` meaning no parameters in C++11 or C?

Several have answered that question and opined that in C, the meaning of the function prototype

void func ()

is that func is a function returning nothing (void) and whose parameters are unknown at this time.

Further they have opined that one could make this declaration and then invoke the function with some arguments such as:

func (1, 2, 3);

So, I did this, I made a test to verify that this works and I'm not surprised that it does.

Here is func.c, which contains main()

#include <stdio.h>

extern void func ();

int main (int ac, char ** av)
{
  func (1, 2, 3);

  return 0;
}

And here is func1.c which contains the function func()

#include <stdio.h>

void func (int a, int b, int c)
{
  printf ( "%d, %d, %d\n", a, b, c );
}

And here are my question(s)

Question 1:

When I run this program, I get, as expected the output 1, 2, 3. Is this a safe way to write code; i.e. can one assume that the ABI will reliably ensure that the invocation of func() in main() will put the three parameters in the right places (registers, stack, whatever) for func() to find them?

Question 2:

If the answer to 1 above is that it is a safe thing to do, then does your answer change if func() is implemented in some language other than C?

Community
  • 1
  • 1
amrith
  • 953
  • 6
  • 17
  • 1
    Even if it were safe in C (I would say not, for obvious reasons), it would be illegal in C++. – juanchopanza Aug 22 '13 at 11:25
  • 2
    @juanchopanza AFAIK it's safe in C. `1, 2, 3` are literals of type `int` - when you invoke `foo(1, 2, 3)`, the not-known-until prototype is assumed to be `void (int, int, int)`. –  Aug 22 '13 at 11:25
  • 1
    Remember that in C there is no function overloading. A big difference between C and C++. – Bathsheba Aug 22 '13 at 11:26
  • Using empty parameter lists in function prototypes in `C` cannot, for this very reason, provide a safe ABI. Don't use that, unless your function is prepared to take *any type and number or arguments*. – Walter Aug 22 '13 at 11:28
  • It's not "safe" in the sense that the compiler can not check your function calls for you to see if the arguments match the prototype. – Paul R Aug 22 '13 at 11:29
  • @H2CO3 OK, but what happens if I call it with `foo(1,2,"Hello", 3.14);`? – juanchopanza Aug 22 '13 at 11:29
  • @juanchopanza Undefined behavior. –  Aug 22 '13 at 11:29
  • 1
    @Walter Empty argument lists are **not** usable for specifying variable arguments. –  Aug 22 '13 at 11:29
  • @H2CO3 OK, that is what I meant by it not being safe. I should have stated that more clearly. – juanchopanza Aug 22 '13 at 11:29
  • @juanchopanza Ah, OK. Let's agree that it works if invoked only with the correct number and type of arguments, and it doesn't otherwise. –  Aug 22 '13 at 11:30
  • @H2CO3 Or rather, it's an obsolete feature, and a good, modern C++ will warn if you try to use it. – James Kanze Aug 22 '13 at 11:39

2 Answers2

12

Are you asking about C or about C++?

C did not originally have function prototypes. You'd write:

extern void func();

and then define it:

void func( a, b, c )
    int a;
    int b;
    int c;
{
    //  ...
}

C++ added function prototypes, and made the above illegal. And the declaration:

extern void func();

declared a function which had no parameters; calling it with arguments was an error, as was defining it with arguments.

C then added function prototypes from C++. But to avoid breaking existing code, it didn't require them, and treated

extern void func();

as before: a function taking an unknown number and types of parameters. So it also added:

extern void func(void);

as a special way of saying that the function doesn't take any parameters. C++ then added this special case for reasons of C compatibility.

The general rule, in C++, is to just write:

extern void func();

The only time you'd use the form with void is in a header that had to be compatible with both languages. In C, of course, this form doesn't do what you want, so you have to add the void. (For now. From what I understand, C has deprecated the older forms, and so could, in the future, behave exactly like C++ in this respect.)

EDIT:

Having looked it up. From the C11 standard, §6.11.6:

The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.

Don't do it in C.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
1

Q1. If the arguments are the right type, then MAYBE it will work (it probably will). But try func(1.2, "blah"); and see what that does - it may "work" in the sense that it doesn't crash - it will certainly compile.

Q2. See answer to Q1. It is not at all safe.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227