编译器警告 - 参数列表有所不同

Posted

技术标签:

【中文标题】编译器警告 - 参数列表有所不同【英文标题】:Compiler warning - something differs in parameter lists 【发布时间】:2017-08-03 20:05:30 【问题描述】:

我正在尝试编译以下源代码,它可以在 gcc 和 Microsoft 的 cl.exe 上成功编译。

void SomethingBeforeExit();

void SomethingBeforeExit()

    // some code
    _exit(0);


int main(int argc, char *argv[])

    // some code
    atexit(SomethingBeforeExit);

但是,我收到了来自cl.exe 的C4113 warning,其中包含以下消息:

SomeCode.c(10): warning C4113: 'void (__cdecl *)()' differs in parameter lists from 'void (__cdecl *)(void)'

正如我所说,源代码仍然编译成功并且似乎可以工作。我的目标是防止在cl 中发生此警告,因为gcc 在编译时不会生成任何警告。

我假设该函数的声明没有被视为void SomethingBeforeExit(void),但是,我不知道如何将函数的参数列表具体声明为void

我将VS14C/C++ 19.00.23918 for x86 用于cl.exegcc v5.4.0 编译器来比较生成的警告。

【问题讨论】:

规则很明确,你传递给atexit的函数必须是(void)。由于历史原因,() 在(某些版本的)C 中并不等同于在 C++ 中的(void) Is it better to use C void arguments "void foo(void)" or not "void foo()"?的可能重复 @Downvoter 不是一个直接重复的问题,我只是不知道() 声明如何被视为@David Schwartz 所述。这个问题是关于C4113 警告,具体与不正确的参数传递有关,而不是使用(void) 是否优于() 哪一行产生了警告:atexit(SomethingBeforeExit); or void SomethingBeforeExit() ? @chux 第一个。 【参考方案1】:

在 C 语言中,函数声明中的空括号并不意味着“没有参数”。相反,它表示任意数量的参数(类似于 C++ 中的...)。也许您要声明的是void SomethingBeforeExit(void)

【讨论】:

谢谢,这是正确答案。我没有意识到 MS 文档中的 identifier2 引用了传递的参数。【参考方案2】:

OP 未使用兼容的 C99/C11 编译器。代码是有效的 C (C99/C11)。

// declares function SomethingBeforeExit and no info about it parameters.
void SomethingBeforeExit();

// declares/defines function SomethingBeforeExit and 
// indirectly specifies the parameter list is `(void)`
// This does not contradict the prior declaration and so updates the parameter signature.
void SomethingBeforeExit() 
   ...  


int main(int argc, char *argv[]) 
  ...
  // `atexit() expects a `void (*f)(void))`
  atexit(SomethingBeforeExit);

在 C89 中,void SomethingBeforeExit() ... 定义仍然没有说明参数列表。这可能是OP问题的原因。

修复:

void SomethingBeforeExit(void)  
  ...

之前的void SomethingBeforeExit(); 声明不需要更新,但最好也更新它,这样参数检查就可以在看不到定义的代码中进行。

【讨论】:

void SomethingBeforeExit() … 的定义仍然没有提供函数的原型。如果您调用SomethingBeforeExit(1, 3.14159, "Apocalypse Then"):,编译器无需抱怨,因为范围内没有原型使其无效。 当我阅读 C11 §6.7.6.3 14 “作为该函数定义的一部分的函数声明器中的空列表指定该函数没有参数。”表示该函数不带参数 - 又名(void)void SomethingBeforeExit( etc.(作为声明/定义)至少将函数原型化为不返回任何内容。 @JonathanLeffler 好吧,至少我的 gcc 版本 5.4.0 同意你的看法。 Jonathan Leffler 和我已经就所有观点达成一致,除了我们在“SomeType FunctionName() ... 是否提供原型”方面存在分歧。 IAC,我们同意SomeType FunctionName(void) … 更好。 感谢您的更新。我相信我们(并且一直)100% 同意明确的 SomeType FunctionName(void) … 定义是首选(以及 SomeType FunctionName(void); 声明也是如此)。

以上是关于编译器警告 - 参数列表有所不同的主要内容,如果未能解决你的问题,请参考以下文章

具有不同编译器的 C++ 和可变参数

是否可以解决“为可变参数参数创建 T 的通用数组”编译器警告?

将对象实例直接作为 const 接口参数传递时,编译器是不是应该提示/警告?

XCode6 Beta 中的编译器警告 - “速记外部参数名称”

gcc和g++常用编译参数

qsort 的第四个参数的“不兼容的指针类型”编译器警告