C:为什么传递的参数少于定义的函数,只显示警告(没有任何错误,它可以 运行 正常)
C : Why passing arguments less then function defined, Only warning shows up (No any error and it can run normally )
这可能是一个特例。当我跟踪 C 代码时,我看到了警告。说
implicit declaration of function 'Wifi_Hosts_Sync_Func' [-Wimplicit-function-declaration]
我试图通过使用外部函数来消除它void *Wifi_Hosts_Sync_Func
但如果我这样做,编译器会显示错误:Wifi_Hosts_Sync_Func 参数太少。
我的问题是为什么这段代码可以工作?! & 为什么程序没有在“运行 时间”崩溃或闪出。
定义的函数需要 5 个参数,调用代码只给出 4 个。
本程序可以运行正常并成功结束。有什么想法吗?
// 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);
^~~~~~~~~~~~~~~~~~~~
在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()");
}
在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");
...
...
}
来自 C89,第 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.
这在 C99 中被删除了,因为它往好里说是令人困惑,往坏里说是有害的。
请注意,与 C++ 不同,C 在定义中使用 ()
表示该函数采用未知数量的参数(none 将是 (void)
)。使用任意数量的参数调用它都可以,只需将所有这些参数压入堆栈,由函数来理解它们。
因此,它只是隐式声明了一个参数数量未知的外部函数,所以它可以编译——尽管它仍然不正确。如果它确实有效,那么你就很幸运,因为名称仍然匹配,所以链接器链接了真正的函数,并且在 cdecl
调用约定中,调用者清除了堆栈,所以函数仍然 运行但将垃圾(可能是外部函数的不相关局部变量)视为第 5 个参数。由于它是一个布尔值,所有发生的事情就是它被解释为 true 或 false 或随机地解释为两者之一(但如果它是一个指针,它可能会造成各种破坏)。
如果您显式定义该函数,则会出现错误,因为您(正确地)用 5 个参数声明了它,但您(错误地)用 4 个参数调用了它。
这就是删除此“功能”的原因:它使代码看似有效但实际上已损坏,这会导致以后出现奇怪的错误和混乱。
不接受任何参数的函数必须声明为
TYPE func(void)
不是 TYPE func()
。永远不要像这样声明函数,因为它是一些历史上贬值的“特性”
在你调用任何函数之前你需要有函数原型让编译器知道return函数有什么类型和参数。
您的函数还必须 return 一个指针。
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;
}
这可能是一个特例。当我跟踪 C 代码时,我看到了警告。说
implicit declaration of function 'Wifi_Hosts_Sync_Func' [-Wimplicit-function-declaration]
我试图通过使用外部函数来消除它void *Wifi_Hosts_Sync_Func
但如果我这样做,编译器会显示错误:Wifi_Hosts_Sync_Func 参数太少。
我的问题是为什么这段代码可以工作?! & 为什么程序没有在“运行 时间”崩溃或闪出。 定义的函数需要 5 个参数,调用代码只给出 4 个。 本程序可以运行正常并成功结束。有什么想法吗?
// 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); ^~~~~~~~~~~~~~~~~~~~
在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()");
}
在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");
...
...
}
来自 C89,第 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.
这在 C99 中被删除了,因为它往好里说是令人困惑,往坏里说是有害的。
请注意,与 C++ 不同,C 在定义中使用 ()
表示该函数采用未知数量的参数(none 将是 (void)
)。使用任意数量的参数调用它都可以,只需将所有这些参数压入堆栈,由函数来理解它们。
因此,它只是隐式声明了一个参数数量未知的外部函数,所以它可以编译——尽管它仍然不正确。如果它确实有效,那么你就很幸运,因为名称仍然匹配,所以链接器链接了真正的函数,并且在 cdecl
调用约定中,调用者清除了堆栈,所以函数仍然 运行但将垃圾(可能是外部函数的不相关局部变量)视为第 5 个参数。由于它是一个布尔值,所有发生的事情就是它被解释为 true 或 false 或随机地解释为两者之一(但如果它是一个指针,它可能会造成各种破坏)。
如果您显式定义该函数,则会出现错误,因为您(正确地)用 5 个参数声明了它,但您(错误地)用 4 个参数调用了它。
这就是删除此“功能”的原因:它使代码看似有效但实际上已损坏,这会导致以后出现奇怪的错误和混乱。
不接受任何参数的函数必须声明为
TYPE func(void)
不是TYPE func()
。永远不要像这样声明函数,因为它是一些历史上贬值的“特性”在你调用任何函数之前你需要有函数原型让编译器知道return函数有什么类型和参数。
您的函数还必须 return 一个指针。
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;
}