Correct way to define a prototype - c

Came across a situation where I was in doubt how to define the prototype the correct way. It´s easier to just look at a simple example:
Document A.c:
#define foo bar
void mon() {
foo();
}
Document B.c:
void bar() {
Do something;
}
Gives following warning:
Warning: Function does not have a full prototype
Normally I would solve it by:
extern void foo(void);
But as example show, the function dont exactly exist but is defined to point on another function. What is the correct way to make a prototype for this?

If the compiler encounters the declaration extern void foo(void); after the #define foo bar for the same source file, it will parse it as extern void bar(void); And the linker will just solve the bar symbol.
Note that you definition of bar is not consistent with the declaration above. The definition of bar should read:
void bar(void) {
// Do something;
}
in C, unlike C++, an argument list of (void) is subtly different from an empty argument list.

I think, that what happens is the following:
The compiler replaces the macro foo with bar but since at that stage bar is not declared anywhere as a function the compiler will complain, that it cannot find it.
Please see more: Are prototypes required for all functions in C89, C90 or C99?

Related

Call C function without declaring it beforehand

Short version: I would like to declare a function in the same statement that calls it. The syntax I'm looking for is something of this sort:
// foo is undeclared in this file, and implemented in another file
int main() {
void* p = (cast_to_function_that_receivs_ints_and_returns_pointer)foo(1,2);
}
Long version:
The following code creates an obvious implicit declaration warning and undefined reference error, because of the call to foo:
// a.c
int main() {
void* p = foo(1,2);
}
I add the following file to the compilation to solve the undefined reference:
// b.c
void* foo(int a, int b) {
return (void*)0xbadcafe;
}
I would now like to solve the implicit declaration. The usual solution is to modify a.c to either #include a declaration to foo or declare it itself, something like:
// a.c
void* foo(int a, int b);
int main() {
void* p = foo(1,2);
}
But I would rather not declare foo, instead modifying the line that calls foo, similar to function pointers syntax, or to the example I posted in the "short versions". Is it even possible?
Assume I am proficient in C and that I have a valid motivation - I would like to "override" the behavior of foo by recompiling with -Dfoo=bar.
So if I understand correctly, your motivation is that you have existing code that looks like
p = bar(1,2);
and you would like to define macros so that it calls foo(1,2) instead. But you don't want to modify the source file to include a declaration of foo - you want to do everything by means of command-line macro definitions. Have I got that right?
Since you've tagged this gcc, perhaps you are willing to consider non-standard gcc extensions to the C language. If so, you can do it with gcc statement expressions, also supported by clang and icc. Define bar to expand to an expression containing a block which declares foo and whose value is a pointer to foo. That is:
#define bar ({ extern void *foo(int, int); foo; })
Or from the command line:
gcc -D'bar=({ extern void *foo(int, int); foo; })' call_bar.c
Try it on godbolt.
This has
A variant would be to define a macro bar(a,b) with two arguments, where the corresponding statement expression actually calls foo:
gcc -D'bar(a,b)=({ extern void *foo(int, int); foo((a), (b)); })' call_bar.c
but this will fail if the original code tries to call p = (bar)(a,b) or tries to take the address of bar.
I'm not aware of any way to get this exact effect in standard C. But a different approach would be to create a header file containing the declaration of foo, and then using -include to "inject" it at the top of the source file:
gcc -include declare_foo.h -Dbar=foo call_bar.c
This isn't technically what you asked for, because at some level it does involve declaring foo "beforehand", but it may still help solve your problem. In this case everything is standard C, but we have moved the "non-portability" from the code to the build process.
On the other hand, if the desired replacement for bar is something simple enough to put in a macro, like the constant return in your example, then you can cut out the middleman foo and just define a macro:
gcc -D'bar(a,b)=((void *)0xbadcafe)' call_bar.c
There's no way around the declaration requirement. You must define a symbol for the compiler to work with. Some compilers allow you to use a pragma or other non-standard feature to create the mapping between the symbol and physical/virtual address.
Compile your mock_foo.c file and link the object file to the program instead of foo.c.
Another approach is only ever call through a macro definition:
#ifdef MOCK_FOO
#define (FOO(a, b) mock_foo(a, b))
#else
#define (FOO(a, b) foo(a, b)
#endif
Otherwise, you have to understand how the compiler/linker and OS/loader work, to correctly hook functions to call mocks. There's a reason tooling for quality mock frameworks cost so much money. They are very complex.
You can cast a function as you call it:
void *p = ((void *(*)(int, int))foo)(1, 2);
It's ugly, I don't see a valid reason for it, but you can.

use of out-of-scope declaration

Code:
void foo() {
extern int a;
extern void b(int);
}
void bar() {
b(9); // ok, warning: use of out-of-scope declaration of 'b'
a=9; // error: use of undeclared identifier 'a'
}
Why the compiler doesn't just give a warning like use of out-of-scope declaration of 'a'?
This is because of the vestigial feature of implicit declaration of functions. If you had just
void bar()
{
b(9);
}
that would actually be 100% valid pre-standard C (well, except that void didn't exist back then, but that's not important right now) equivalent to writing
void bar()
{
extern int b();
b(9);
}
(Remember that an empty parameter list in a function declaration does not mean that the function takes zero arguments. It means the function takes an unspecified number of arguments.)
Now, when you have
void foo()
{
extern void b(int);
}
void bar()
{
b(9);
}
the implicit declaration means it's like you wrote
void foo()
{
extern void b(int);
}
void bar()
{
extern int b();
b(9);
}
The two declarations of the external symbol b are not compatible. If they were both visible in the scope of bar, this would be a constraint violation ("X is a constraint violation" is the closest the C standard ever comes to saying "a program that does X is invalid and the compiler must reject it"). But they're not, so instead, the program's meaning is undefined. clang seems to have decided to apply the declaration from the foo scope but also warn you about it, which seems fair to me. gcc does treat it as an error:
test.c:6:5: error: incompatible implicit declaration of function ‘b’
b(9);
^
test.c:2:17: note: previous implicit declaration of ‘b’ was here
extern void b(int);
^
("previous implicit declaration" is not quite right, but that is also not important right now.)
You can probably see how this sort of thing could lead to hard-to-find bugs, which is why modern best practice is to declare stuff with external linkage only at file scope, and to declare all functions with full prototypes.
Only functions are ever implicitly declared, which is why a gave a hard error; in your original example, a is completely invisible to bar. (Note that if you had redeclared it with a different type, that would also make the program's meaning undefined.)

Compiling without including a header file

In a particular C project, a file say file1.c uses a function say FUNCTION2(). The FUNCTION2() is declared in file2.c. An extern declaration of FUNCTION2() is there in file1.h
The file1.c adds only file1.h.
In file1.h, the file2.c/file2.h is not added. Still the compilation is successful and the functionality is working.
In the compilation list of the project, file2.c/file2.h is compiled first. But is that possible to call functions without adding the header file?
You can, but I wouldn't advise it. You have arranged things to force the compiler to exploit implicit declaration:
int main()
{
foo(2); /* The compiler emits this by implicit declaration. */
return 0;
}
int foo(int x)
{
return x;
}
In your explicit case, extern is telling the compiler to expect foo to come from a different compilation unit.
The standard thing to do would be to put a prototype of foo in a header and include that.

how to clean the implicit declaration of function in C?

I have a question regarding to the function declaration:
I declared a function in b.c
//b.c
void getNumber();
//common header
common.h
In a.c I use it like this:
//a.c
#include "common.h"
void getInfo()
{
getNumber();
}
but it complain the getNumber is implicit declaration of function, what is the reason?
add the following line to common.h
void getNumber();
the b.c file should contain the function definition in this way
void getNumber() {
....
}
You need to declare or define your function first before using it.
If your declaration void getNumber(); was read by the compiler after its first use (void getInfo()), you would get the warning warning: implicit declaration of function ‘getNumber’. This happened because the compiler, when first encountering getNumber in void getInfo() had to guess its return type - hence the warning. I think this is what you are doing even though your example code does not show it that way.
If your void getNumber(); was read by the compiler first, no warning would occur.
Putting your function declaration in a header file like is a good idea. Be sure to include "common.h" first before your getInfo().

extern with global definition of variable in c

I have the following source code which interests me.
#include <stdio.h>
extern int foo;
int foo = 32;
int main()
{
printf("%d", foo);
}
This a perfectly normal piece of code, and when I compile it with
gcc -Wall -Wextra -pedantic foo.c
I get no warnings.
And it seems weird, because a variable is defined both as external, and also global in the same file.
I'm quite sure that it's easy to the linker to find the reference for the external variable in the same file, but doesn't it look like a coding error? And if so, why doesn't the compiler warn about this?
There's nothing weird. You first made a declaration of a variable (you promised the compiler that it exist) and then you actually defined it. There's no problem in that.
Also, by default, all variables that aren't local to functions and aren't defined as static are extern.
You seem to misunderstand what extern does. extern simply makes your declaration just a declaration instead of a definition.
int i; //definition of i
extern int i; //declaration of i
It is perfectly normal to have multiple declarations of the same variable, but only one definition should be present in the whole program. Compare this with a function
void f(void); //declaration
void f(void) //definition(and redeclaration)
{
} //definition
In order to use a variable or function, you only need its declaration. Its definition may appear anywhere in the program (the linker will find it). Anywhere can be the same file, another file, or even an external library.
And it's seems weired, because a variable is defined both as external, and also global in the same file.
extern int foo;
says: it declares without defining an object of type int named foo.
int foo = 32;
it declares and defines an object of type int named foo with external linkage.
There is no contradiction and it is valid C code.
The difference is that the former is a declaration -> extern declares a variable and says it will be available somewhere around. You can have as many declarations as you want and the latter is a definition which must be there exactly once.
So there should be no warning and no error.
extern is a way to provide visibility to a variable that is defined elsewhere...
extern is like a promise...
in example.h
extern int g;// promises that this will be in the object code to anything that includes example.h
example. c
int g;

Resources