Reputation: 39
this maybe is a special case. When i tracing a C code i saw warning . said
implicit declaration of function 'Wifi_Hosts_Sync_Func' [-Wimplicit-function-declaration]
i tried to eliminate it by using extern the function void *Wifi_Hosts_Sync_Func
but if i do this compiler shows Error : Wifi_Hosts_Sync_Func too few arguments.
my question is WHY this code can works?! & WHY program didn't crash or flash out on "run time". defined function need 5 argument ,calling code only gives 4 . this program can run normally and succeed end. any ideas?
// warning msg. ../../../../git/source/TR-181/ml/cosa_wifi_dml.c: In function 'WiFi_HostSyncThread': ../../../../git/source/TR-181/ml/cosa_wifi_dml.c:756:2: warning: implicit declaration of function 'Wifi_Hosts_Sync_Func' [-Wimplicit-function-declaration] Wifi_Hosts_Sync_Func(NULL,0, NULL, 1); ^~~~~~~~~~~~~~~~~~~~
in cosa_wifi_dml.c
void *WiFi_HostSyncThread()
{
fprintf(stderr,"[TRACE] before Wifi_Hosts_Sync_Func()");
Wifi_Hosts_Sync_Func(NULL,0, NULL, 1);
fprintf(stderr,"[TRACE] after Wifi_Hosts_Sync_Func()");
}
in cosa_wifi_apis.c
void *Wifi_Hosts_Sync_Func(void *pt, int index, wifi_associated_dev_t *associated_dev, BOOL bCallForFullSync, BOOL bCallFromDisConnCB )
{
fprintf(stderr,"[TRACE] Wifi_Hosts_Sync_Func() Call in.\n");
...
...
}
Upvotes: 1
Views: 111
Reputation: 29011
From C89, Section 3.3.2.2:
If the expression that precedes the parenthesized argument list in a function call consists solely of an identifier, and if no declaration is visible for this identifier, the identifier is implicitly declared exactly as if, in the innermost block containing the function call, the declaration
extern int identifier();
appeared.
This was removed in C99 though because it's confusing at best and harmful at worst.
Note that unlike C++, C uses ()
in the definition to say that the function takes an unknown number of arguments (none would be (void)
). Calling it with any number of arguments would work and just push all those arguments to the stack and it would be up to the function to make sense of them.
So, it just implicitly declared an external function with an unknown number of arguments, so it compiles - it's still incorrect though. And if it does work anyway then you just got lucky because the name still matched so the linker linked the real function and in the cdecl
calling convention the caller clears up the stack, so the function would still run but see garbage (probably an unrelated local variable of the outer function) as 5th argument. Since it's a boolean value, all that happens is that it's interpreted as either true or false or randomly one of the two (but if it were, say, a pointer, it could wreak all kinds of havoc).
If you explicitly define the function, you get an error, because you (correctly) declared it with 5 arguments but you (incorrectly) call it with 4.
And this is why this "feature" was removed: It makes code appear to work that is actually broken, which leads to strange bugs and confusion later on.
Upvotes: 4
Reputation: 67476
Function which does not take any arguments has to be declared as
TYPE func(void)
not TYPE func()
. Never declare functions like this as it is some historical depreciated "feature"
Before you call any function you need to have the function prototype to let complier know what return type and parameters function has.
Your function also has to return a pointer.
void *Wifi_Hosts_Sync_Func(void *pt, int index, wifi_associated_dev_t *associated_dev, BOOL bCallForFullSync, BOOL bCallFromDisConnCB );
void *WiFi_HostSyncThread(void)
{
void *result;
fprintf(stderr,"[TRACE] before Wifi_Hosts_Sync_Func()");
result = Wifi_Hosts_Sync_Func(NULL,0, NULL, 1); // and now you will have the error here.
fprintf(stderr,"[TRACE] after Wifi_Hosts_Sync_Func()");
return result;
}
Upvotes: 1