Call C function without declaring it beforehand - c

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.

Related

why no need to add `extern` for external functions?

below is my code:
//main.c
//I'm not using header file here,I know it is bad practice, it is just for demo purpose.
int main()
{
func();
return 0;
}
//test.c
void func()
{
...
}
we can see that above code compiles and can be linked by linker, but the same thing doesn't apply to variables as:
//main.c
int main()
{
sum += 1;
return 0;
}
//test.c
int sum = 2020;
then this code won't compile and can't be linked, and we have to add extern int sum; before main function in main.c.
But why we don't need to add extern in main.c as:
//main.c
extern void func(); //or `void func();` since functions are by default external
// without above line, it still compile
int main()
{
func();
return 0;
}
is it a little bit inconsistent here?
Note: by saying " Functions are by default external.",my understanding is: we can save some keystokes without typing extern , so void func(); == extern void func();, but we still need to add void func(); before main function in main.c, isn't it?
Both programs are incorrect since C99 and may be rejected by the compiler. An identifier may not be used in an expression without previously being declared.
In C89 there was a rule that if you write something that resembles a function call, and the function name has not previously been declared, then the compiler inserts a function declaration int f(); . There was not a similar rule for use of other identifiers that aren't followed by parentheses.
Some compilers (depending on compiler flags) will, even if set to C99 or later mode, issue a diagnostic and then perform the C89 behaviour anyway.
Note: your program still causes undefined behaviour in C89 because the implicit declaration is int func(); but the function definition has void func() which is incompatible type.
The compiler doesn't need to know anything about a function, in order to generate code to call it. In the absence of a prototype, it might generate the wrong code, but it can generate something (in principle, at least -- standards-compliance might forbid it by default). The compiler knows the calling convention for the platform -- it knows to put the function arguments onto the stack or into registers as required. It knows to write a symbol that the linker can later find and fix up, and so on.
But when you write "sum++", the compiler has no clue, lacking a declaration, how to generate code for that. It doesn't even know what kind of thing "sum" is. The code needed to increment a floating-point number will be completely different to that needed to increment an integer, and may be different from that needed to increment a pointer. The compiler doesn't need to know where "sum" is -- that's the linker's job -- but it needs to know what it is, to produce meaningful machine code.
But we don't need to add extern for the function in main.c as extern void func(); or void func();(as functions are implicitly extern prefixed) and the code still compile?
That's correct. Functions are by default external.
To make functions specific to a local source file (translation unit), you need to specific static for them.
Variables, on the other hand, are visible in the source file only. If you want to make some variable visible outside the source file where it is defined, you need extern for it.
There are two completely different topics - function prototypes and linkage.
void foo(void);
provides the extern function prototype needed by compiler to know the number and type of parameters and the type of the return value. Function has an external linkage - ie can be accessed by other compilation units
static void foo(void);
provides the static function prototype. Function has an no external linkage - ie it cannot be accessed by other compilation units
By default functions have an external linkage.
Objects (global scope).
int x;
Defines the object x having the external linkage and type int.
If you define another x object in another compilation unit the linker will complain and emit an error.
extern int x;
Only declares the object x without defining it. The object x has to be defined in other compilation unit.

Using functions with two seperate files

Files: A(main), B
I have learned that B's function can't be use in A without
funcntion definitions.
But my code ran normally with A, B files without function definitions
This is my code:
B.c
void a()
{
printf("hi");
}
A.c
#include <stdio.h>
void main()
{
a();
}
What is it? I'm confused.
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
addendum...
sorry for my bad question.
my code works well with error.
but i couldn't see error.
but i have more question for difference between
'void a();'
'extern void a();'
Once upon a time, C did not require prior declaration of all functions. Many compilers still let you get away with this.
In file A.c, when you called
a();
where a was a function the compiler has never seen before, the compiler assumed that the declaration
extern int a();
was in scope. That is, the compiler assumed that a was a function taking unspecified arguments and returning int.
Or, that used to be the rule. That rule is no longer in C, so yes, you are supposed to explicitly declare all your functions before you call them. Most of today's compilers will warn you when they apply the old rule, and many aren't willing to apply the rule at all, or at least, not unless you use a non-default option flag requesting them to. But it sounds like your compiler is still willing to apply the rule without warning or error. That's great if you're compiling a bunch of very old code, but it's not so great if you're trying to learn modern C.
Now, in this case you have the additional problem that the actual definition of function a in file B.c defines it as returning void, not int, so theoretically that's wrong, too. But, in practice, the error of misdeclaring (or mis-calling) void- versus int-returning functions is an innocuous one, that doesn't cause any real problems. (It's still wrong, though, and worth avoiding.)
I think you know this, but a correct setup would either be to have file A.c look like this:
#include <stdio.h>
extern void a(void);
int main()
{
a();
}
or else to create the file B.h containing
extern void a(void);
and then to have file A.c look like this:
#include <stdio.h>
#include "B.h"
int main()
{
a();
}
(Note that I have also changed void main() to int main(), for correctness. If you're using an old compiler, as it sounds like you are, you may also have to add the line return 0; at the end of main().)
Addendum. You had also asked about that extern keyword. It has to do with the distinction between declarations and definitions. But this distinction plays out slightly differently for functions, versus global variables.
Declarations explain what type something has. Definitions explain what type something has, and they additionally allocate memory for the something, and supply its initial value.
These are declarations:
extern int i;
int f(int);
extern int f2(int, double);
These are definitions:
int i;
int i2 = 2;
int f(int x) { return 2 * x; }
int f2(int n, double x) { return n * x; }
The keyword extern explicitly says, "This is a declaration, the definition is somewhere else." For global variables, this makes a big difference. But for functions, when you say int f(int);, the compiler can tell, when it finds a , instead of a {, that this is a declaration (not a definition), so the keyword extern is optional in function declarations.
(Also, functions are always global in C; there are no local functions.)
See also section 4.2 and section 4.3 of these course notes.

C function weird syntax [duplicate]

I'm relatively new to C. I've come across a form of function syntax I've never seen before, where the parameter types are defined after that parameter list. Can someone explain to me how it is different than the typical C function syntax?
Example:
int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
That's the old-style syntax for parameter lists, which is still supported. In K&R C you could also leave off the type declarations and they would default to int. i.e.
main(argc, argv)
char *argv[];
{
return 0;
}
would be the same function.
What's also interesting is the calling convention difference of functions with, and functions without a prototype. Consider an old style definition:
void f(a)
float a; {
/* ... */
}
In this case, the calling convention is that all arguments are promoted before being passed to the function (for example, a float argument is first promoted to double, before being passed). So if f receives a double but the parameter has type float (which is perfectly valid) the compiler has to emit code that converts the double to a float prior to executing the function's body.
If you include a prototype, the compiler does not do such automatic promotions anymore and any data passed is converted to the types of the parameters of the prototype as if by assignment. So the following is not legal and results in undefined behavior:
void f(float a);
void f(a)
float a; {
}
In this case, the function's definition would convert the submitted parameter from double (the promoted form) to float because the definition is old-style. But the parameter was submitted as a float, because the function has a prototype. For example, clang gives
main.c:3:9: warning: promoted type 'double' of K&R function parameter is not compatible with the parameter type 'float' declared in a previous prototype [-Wknr-promoted-parameter]
Your options of solving the contradictions are the two following:
// option 1
void f(double a);
void f(a)
float a; {
}
// option 2
// this declaration can be put in a header, but is redundant in this case,
// since the definition exposes a prototype already if both appear in a
// translation unit prior to the call.
void f(float a);
void f(float a) {
}
Option 2 should be preferred if you have the choice because it gets rid of the old style definition up front. If such contradicting function types for a function appears in the same translation unit, the compiler will usually tell you (but is not required). If such contradictions appear over multiple translation units, the error will possibly go unnoticed and can result in hard to predict bugs. It is best to avoid these old style definitions.
This is the so caller K&R style or old-style declaration.
Note, that this declaration is significantly different from the modern declaration. K&R declaration does not introduce a prototype for the function, meaning that it doesn't expose the types of the parameters to the outside code.
There is no difference, it is just that that is the old syntax for function declarations in C -- it was used pre ANSI. Never write such code unless you plan to give it to your friends from the 80's. Also, never depend upon implicit type assumptions (as another answer seems to suggest)
While the old syntax for function definition still works (with warnings, if you ask your compiler), using them does not provide function prototypes.
Without function prototypes the compiler will not check if the functions are called correctly.
#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }
int bar(x)
double x;
{ return printf("%f\n", x); }
int main(void)
{
foo(42); /* ok */
bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
return 0;
}
When the program is run, the output on my machine is
$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
Its just the same but old fashion. You probably found it is some old, legacy code.
Old or not, I would argue what is old and what not.. like the pyramids are ancient, but none of today’s so-called scientists have a clue how they were made. Looking back, old programs still work today without memory leaks, but these "new" programs tend to fail more than often. I see a trend here.
Probably they saw functions as structs which have an executable body. Knowledge of ASM is needed here to solve the mystery.
Edit, found a macro which indicates you do not need to supply argument names at all.
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
Here is an usage example, library is zlib-1.2.11.
ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
So my second guess would be for function overloading, otherwise these arguments had no use. One concrete function, and now infinite amount of functions with same name.

extern function during linkage?

I have this weird thing:
in a file1.c there's
extern void foo(int x, int y);
..
..
int tmp = foo(1,2);
in the project I could find only this foo():
in file2.c :
int foo(int x, int y, int z)
{
....
}
in file2.h :
int foo(int x, int y, int z);
file2.h isn't included in file1.c (this is why who wrote it used extern, i guess).
this project compiles fine, I think that's because in file1.c foo() will be looked for only during linkage, am I right?
but my real question is : why is the linkage succssful ?
after all, there is no such function as foo with 2 parameters....
and i'm in c .. so there's no overloading..
so what's going on ?
Because there is no overloading, the C compiler does not decorate the function names. The linker finds in file2.c a reference to function foo and in file1.c it finds a function foo. It cannot know their parameter lists do not match and happily use them.
Of course, when the function foo runs the value of z is garbage and the behavior of the program becomes unpredictable from that point on.
Calling a function with the wrong number (or types) of arguments is an error.
The standard requires the implementation to detect some, but not all of them.
What the standard calls an implementation, is typically a compiler with a separate linker (and some other things), where a compiler translates single translation units (that is, a preprocessed source file) into object files, which later get linked together.
While the standard doesn't distinct between them, its authors of course wrote it with the typical setup in mind.
C11 (n1570) 6.5.2.2 "Function calls", p2:
If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters. Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter.
This is in a "constraints" section, which means, the implementation (in this case, that's the compiler) must complain and may abort translation if a "shall" requirement is violated.
In your case, there was a prototype visible, so the arguments of the function call must match with the prototype.
Similar requirements apply for a function definition with a prototype declaration in scope; if your function definition doesn't match the prototype, your compiler must tell you. In other words, as long as you ensure that all calls to a function and that function's definition are in the scope of the same prototype, you are told if there is a mismatch. This can be ensured if the prototype is in a header file which is included by all files with calls to that function and by the file containing its definition. We use header files with prototypes exactly for that reason.
In the code shown, this checking is by-passed by providing a non-matching prototype and not including the header file2.h.
Ibid. p9:
If the function is defined with a type that is not compatible with the type (of the expression) pointed to by the expression that denotes the called function, the behavior is undefined.
Undefined behaviour means, the compiler is free to assume it doesn't happen, and is not required to detect if it does.
And in fact, on my machine, the generated object files from file2.c (I inserted a return 0; to have some function body), don't differ if I remove one of the function arguments, which means, the object file doesn't contain any information about the arguments und thus a compiler seeing only file2.o and file1.c hasn't got any chance to detect the violation.
You've mentioned overloading, so let's compile file2.c (with two and three arguments) as C++ and look at the object files:
$ g++ file2_three_args.cpp -c
$ g++ file2_two_args.cpp -c
$ nm file2_three_args.o
00000000 T _Z3fooiii
$ nm file2_two_args.o
00000000 T _Z3fooii
Function foo has its arguments incorporated into the symbol created for it (a process called name mangling), the object file indeed carries some information about the function types. Accordingly, we get an error at link time:
$ cat file1.cpp
extern void foo(int x, int y);
int main(void) {
foo(1,2);
}
$ g++ file2_three_args.o file1.cpp
In function `main':
file1.cpp:(.text+0x19): undefined reference to `foo(int, int)'
collect2: error: ld returned 1 exit status
This behaviour would also be allowed for a C implementation, aborting translation is a valid manifestation of undefined behaviour at compile or link time.
The way overloading in C++ is usually done actually allows such checks at link time. That C doesn't have built-in support for function overloading, and that the behaviour is undefined for the cases where the compiler cannot see the type mismatches, allows to generate symbols for functions without any type information.
First of all
extern void foo(int x, int y);
means exactly the same thing as
void foo(int x, int y);
The former is just an overly explicit way to write the same thing. extern fills no other purpose here. It is like writing auto int x; instead of int x, it means the very same thing.
In your case, the "foo" module (which you call file2) contains the function prototype as well as the definition. This is proper program design in C. What file1.c should be doing is to #include the foo.h.
For reasons unknown, whoever wrote file1.c didn't do this. Instead they are just saying "elsewhere in the project, there is this function, do not care about its definition, that's handled elsewhere".
This is bad programming practice. file1.c shouldn't concern itself with how things are defined elsewhere: this is spaghetti programming which creates a needless tight coupling between the caller and the module. There is also the chance that the actual function doesn't match the local prototype, in which case you would hopefully get linker errors. But there are no guarantees.
The code must be fixed like this:
file1.c
#include "foo.h"
...
int tmp = foo(1,2);
foo.h
#ifndef FOO_H
#define FOO_H
int foo(int x, int y, int z);
#endif
foo.c
#include "foo.h"
int foo(int x, int y, int z)
{
....
}

Does the order of C objects matter?

Does the order in which C objects appear on the file matter?
For example, in functions, if I create two functions and the one above references the other one will it work? (Yes it will, I've tried it.)
Is the same in effect for static functions, INLINE functions, etc.?
Is the same in effect for structs? What happens if I reference a struct which is defined further down on the .c file?
Is this to any extend compiler-specific? How does the compiler work in this case? Does it first scan the whole file for all declarations/definitions and then attempts to dereference functions/symbols?
First, if by "if I create two functions and the one above references the other one will it work?" you mean something like this:
int foo()
{
return bar();
}
int bar()
{
return 0;
}
Then the compiler may do educated guesses at what bar() is, but it will at least spit a warning if bar() wasn't already declared. For symbols that can't be called (like variables or types), it's an outright error if they're used before they're declared.
In C, whenever you use an identifier (and no matter the kind of the identifier: it may be a function, a variable, a type, etc.), it should be declared beforehand. The various modifiers you may add to any identifier (like you said, static, inline and all the others) have no impact on this.
Do not confuse declaration and definition. A declaration is just telling the compiler that a name exists; a definition actually tells the compiler what it is.
For instance, this is a definition:
int bar() { return 4; }
Notice how it has a body, with (simple) code inside.
This is the matching declaration:
int bar();
The compiler will gladly accept the use of a function as soon as it sees either the declaration or the definition for it. For organization reasons and better flexibility, it's often better to write declarations for all your functions at the top of your C file (or inside an included header file) then the definitions.
So, my first example should look like this:
int foo();
int bar();
int foo()
{
return bar();
}
int bar()
{
return 0;
}
With the declarations above the C code, I can change the order of the functions in any way I like.
Typically something must be defined above where you use it. You can avoid this in different ways for different situations.
For functions, just provide a prototype above where it's called and all will be well.
int trol(int a, int b);
// use trol(int, int)
int trol(int a, int b) { }
If you have two functions, a and b, and they call each other and are defined in the order of: a, b, then you must provide b's prototype above the definition of a. a's prototype is not required because it is defined above where it is used inside b. Then the compiler will have no problems.
One other special case for functions is that you can use a function without declaring it and the compiler will try to infer the signature from the call. This answer explains it pretty well I think: Must declare function prototype in C?
For structs, you can use pointers to them before they are actually defined (but you can't access any of the fields) by providing a forward declaration:
struct s;
// use s*'s
struct s { };
(The above scenario facilitates recursive data structures like linked lists and trees; you can use pointers to structs before they are fully defined because the size of any type of pointer is constant.)
It matters, because if the compiler doesn't know what the function is - it will try to 'guess' (create a default int foo() prototype with matching parameters), and if your call is incorrect - you'll have mismatches (build errors, implicit castings, whatever).
It is common practice (if not even required) to declare the function before calling it (through prototypes aka forward declarations).
For functions with variable parameter lists (like printf) you must have a forward declaration for them to work properly. For example this code will not compile:
int foo(int a)
{
b(a);
b("hello", "kitty");
}
void b(int a, ...)
{
printf("%d", a);
}
But this - will:
#include <stdio.h>
int foo(int a)
{
return b(a);
}
int b(int a)
{
return printf("%d", a);
}
(with warning about the implicit forward declaration)
So in order to avoid dealing with the order of the objects in the file - use prototyping (forward declarations) to let the compiler know what's following.
From my experience, everything in C has to be written with the referenced "object" before the reference is made. I don't think this is specific to any compiler, but maybe there are some which I haven't found. Basically, everything always has to be:
Object Declaration
...
Object Reference

Resources