Is it dubious the use of a non-prototype function declaration?

Is this a valid C code (C99)?

int f(); int g(int x) { if (x<0) return f(x); else return f(x,x); } 

Obviously, a program has undefined behavior if g ever called with a negative argument, and f not a function that takes a single int argument, or if g ever called with a non-negative argument and f not a function that accepts two arguments int . But otherwise?

As an example, consider this separate source file that calls g from the above and provides f :

 int g(); #ifdef FOO int f(int a, int b) { return a+b; } int main() { return g(1); } #else int f(int a) { return a; } int main() { return g(-1); } #endif 
+3
source share
5 answers

Let me ask you the opposite: why would it not . I really cannot find any arguments or rules prohibiting the above code. A function call in the corresponding other branch is never executed (although the discussion in the comments indicates that it is not so simple!).

+4
source

C99 (6.5.2.2 Functional Calls, Clause 8) says that the number and types of parameters and arguments are not โ€œcomparedโ€ unless the function definition has a prototype.

I saw this (ab) used in the wild with function pointers. The void (*)() array contains function pointers void (*)(struct Client *) and void (*)(struct Client *, int parc, char *parv[]) . Based on the index of the array, the code passed additional parameters or not.

In this case, the compiler does not have a (reasonable) way to check the number of parameters in advance, even if it has all the relevant codes.

I think this is dirty code, and I fixed this particular instance.

+3
source

I would agree that it is valid until an incorrect function call is ever evaluated using the abstract C machine.

There is another, simpler way to come to your conclusion about the linker: since this is allowed:

 int f(); int (*fp)() = f; 

The linkerer should be able to find the address f() without knowing its actual definition. Therefore, its symbol must be able to determine without knowing the actual definition.

+2
source

What if he f(int x, ...) and he looks at the sign of his first argument to find out how many (0 or 1) varargs it received?

0
source

It really is (well, it may depend on which standard you use). You should read something about calling conventions .

Basically, if f takes one or nothing arguments, I would not expect any problems.
If f takes two or more arguments, it can be expected that other arguments (other than the first) will have undesirable (apparently random) values.

Consider this piece of code:

 int f(int x, int y); int g(int x) { int k; //No value if (x<0) return f(x, k); else return f(x, x); } 

Of course, this is a bad idea. You must explicitly specify all arguments.

You can also use int f(void); to explicitly declare that f does not accept any arguments.

Remember that overloading C ++ functions can cause problems, but I assume this is not a concern, since you noted your question with c . In addition, some challenges can cause serious problems.

0
source

Source: https://habr.com/ru/post/1336342/


All Articles