C:为什么传递的参数少于函数定义的参数,仅显示警告没有任何错误,它可以正常运行

问题描述

这也许是特例。当我追踪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,NULL,1);
  ^~~~~~~~~~~~~~~~~~~~

在cosa_wifi_dml.c

void *WiFi_HostSyncThread()
{
    fprintf(stderr,"[TRACE] before Wifi_Hosts_Sync_Func()");
    Wifi_Hosts_Sync_Func(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节:

如果函数调用中带括号的参数列表之前的表达式仅由一个标识符组成,并且如果该标识符没有可见的声明,则该标识符将隐式声明为与包含该函数调用的最里面的块完全相同,声明extern int identifier();出现了。

尽管C99充其量是令人困惑的,而最坏的情况是有害的,但在C99中已将其删除。

请注意,与C ++不同,C在定义中使用()表示该函数接受未知数量的参数(没有一个(void))。可以使用任意数量的参数来调用它,只要将所有这些参数推入堆栈即可,这要由函数来理解。

因此,它只是隐式声明了带有未知数量的参数的外部函数,因此可以进行编译-尽管它仍然不正确。而且,如果它确实可以正常工作,那么您就很幸运,因为名称仍然匹配,因此链接程序链接了实函数,并且在cdecl调用约定中,调用程序清除了堆栈,因此该函数仍将运行,但会看到垃圾(可能是外部函数的无关局部变量)作为第5个参数。由于它是一个布尔值,所以发生的一切都是将其解释为true或false或随机地将其解释为两者之一(但是,如果它是一个指针,则可能造成各种破坏)。

如果显式定义该函数,则会出现错误,因为您(正确)使用5个参数声明了该函数,但是(错误地)使用了4个参数对其进行了调用。

这就是为什么删除此“功能”的原因:它使代码看上去可以正常工作,但实际上已经损坏了,这导致以后出现奇怪的错误和混乱。

,
  1. 不接受任何参数的函数必须声明为 TYPE func(void)不是TYPE func()。永远不要声明这样的函数,因为它是一些历史上已贬值的“功能”

  2. 在调用任何函数之前,您需要具有函数原型以使编译器知道函数具有什么返回类型和参数。

您的函数还必须返回一个指针。

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,NULL,1);   // and now you will have the error here.
    fprintf(stderr,"[TRACE] after  Wifi_Hosts_Sync_Func()");
    return result;
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...