Reputation: 422
When you don't include and use malloc, we get implicit declaration warning.
"warning: incompatible implicit declaration of built-in function ‘malloc’"
This warning is due to fact that compiler assumes malloc defined as int malloc(size) while it is void* malloc(size)
.
But how does it know about void* malloc(size)
? We have not included anything in header files. So how is it comparing it against something that is not included.
And after that, how does my code work? How does it find correct malloc definition and use it?
Is there any sequence order in which function definitions are scanned?
Upvotes: 3
Views: 917
Reputation: 320361
The reason you got this specific warning is malloc
being a built-in function in this specific compiler (as the warning states). This function receives special treatment from the compiler. The compiler has intrinsic knowledge about how this function has to be declared, so when the implicit declaration contradicts the proper declaration, the warning is issued immediately.
In general case, with ordinary (non-built-in) functions, you will get a similar waning for an implicitly declared function when the compiler actually discovers the first explicit declaration for the same function (assuming there's a mismatch between the two). In that case the warning will be issued later: not at the point of the call, but at the point of explicit declaration. That's the way it works with ordinary functions.
But with such standard (built-in) functions as malloc
the compiler allows itself a bit of "cheating".
Upvotes: 1
Reputation:
But how does it know about
void* malloc(size)
? We have not included anything in header files. So how is it comparing it against something that is not included.
Most modern compilers have a built-in (i. e. hard-coded in the compiler) list of common standard library functions, so the compiler knows what the declaration should be even without the function being declared (explicitly or implicitly) or called.
This does not mean that the correct declaration will be used (because the implicit declaration rule overrides the compilers apparent knowledge), but at least you know that you're doing something wrong.
The exact purpose of these built-ins is that the compiler can warn you if you forget to include a header file. (There other purposes as well, such as the opportunity to perform intrinsic optimization by knowing the semantics/implementation of a built-in function, but those do not apply here.)
Upvotes: 1
Reputation: 21213
When you call a function f
that has never been defined, an implicit declaration like this takes place:
int f();
Note that you can still pass arguments to f
, since it was not declared int f(void);
(this is for backwards compatibility with K&R C).
Thus, the compiler doesn't "know" that malloc receives a size argument, in fact you can pass it what you want, it doesn't care.
So, the mere fact that the code works is pure luck. In the case of malloc, if the code works, it just means that the size of an integer is the same size as a pointer - no more, no less - so, you can still call malloc and assign its result to a pointer, since no bits were trimmed / are missing.
The true function is found in the linking stage, after compilation takes place. By this time, your code was already compiled with a wrong function prototype. Of course, if the linker can't find the function anywhere in its path, an error is reported and everything is aborted.
For the case of malloc, and other standard library functions, there may be builtin functions to increase performance. There's even an option for gcc to disable builtin functions (-fno-builtin
or -fno-builtin-function
). From gcc manpage:
GCC normally generates special code to handle certain built-in functions more efficiently; for instance, calls to "alloca" may become single instructions that adjust the stack directly, and calls to "memcpy" may become inline copy loops. The resulting code is often both smaller and faster, but since the function calls no longer appear as such, you cannot set a breakpoint on those calls, nor can you change the behavior of the functions by linking with a different library. In addition, when a function is recognized as a built-in function, GCC may use information about that function to warn about problems with calls to that function, or to generate more efficient code, even if the resulting code still contains calls to that function.
So, in the particular case of malloc, this is how the compiler "knows" its usual signature. Try to compile this code with gcc:
int main(void) {
char *a = malloc(12, 13, 14, 15);
return 0;
}
You will see it will abort with a compilation error:
test.c:3: error: too many arguments to function `malloc'
If you use the option -fnobuiltin
, the error goes away and the warning is different:
test.c:3: warning: implicit declaration of function `malloc'
This is the same warning you get every time you use a regular function that was not previously defined, because now the compiler is ignoring what he "knows" about these functions. This example uses gcc, but other compilers will have similar behavior.
Upvotes: 5
Reputation: 780673
It doesn't find the correct definition if you don't declare it properly (either with an explicit declaration in your source code, or by including the proper header). It uses a default, implicit declaration for any functions that are called before they're declared. The implicit declaration includes the assumption that the function returns int
.
It's then comparing the default declaration with the way that you called the function. It notices that you're assigning the result to a pointer variable rather than an integer, so it warns you that these are incompatible.
Upvotes: 0