如何摆脱-Wimplicit-function-declaration

How do I get rid of -Wimplicit-function-declaration

提问人:Rodion Iskhakov 提问时间:11/8/2023 最后编辑:Vlad from MoscowRodion Iskhakov 更新时间:11/8/2023 访问量:83

问:

我已将我的 C 源代码拆分为 2 个文件:和。main.csecondary.c

/* main.c */

#include <stdlib.h>
//#include "secondary.c"

int main ()
{
         extern int my_var;

         my_var = 123;
         print_value ();
         exit (0);
}
/* secondary.c */

#include <stdio.h>
int my_var;

void print_value ()
{
        printf("my_var = %d\n", my_var);
}

我使用以下命令来编译它们:

$gcc -Wall main.c secondary.c

但在这种情况下,我收到以下警告:

snowgold@iskhakov-r:~/clang$ gcc -Wall main.c secondary.c
main.c: In function ‘main’:
main.c:9:9: warning: implicit declaration of function ‘print_value’ [-Wimplicit-function-declaration]
    9 |         print_value();
      |         ^~~~~~~~~~~

然后我决定包含在 .为此,我输入了 。secondary.cmain.c#include "secondary.c"main.c

在这种情况下,我收到以下错误:

snowgold@iskhakov-r:~/clang$ gcc -Wall main.c secondary.c
/usr/bin/ld: /tmp/ccKKRtFc.o:(.bss+0x0): multiple definition of `my_var'; /tmp/ccx4HrNG.o:(.bss+0x0): first defined here/usr/bin/ld: /tmp/ccKKRtFc.o: in function `print_value':
secondary.c:(.text+0x0): multiple definition of `print_value'; /tmp/ccx4HrNG.o:main.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status

我该怎么做才能摆脱?-Wimplicit-function-declaration

c gcc 编译器错误 函数声明

评论

1赞 Retired Ninja 11/8/2023
在调用函数之前,请提供该函数的原型。 通常,您会将其放在标头中,并将该标头包含在使用该函数的文件中。void print_value ();
0赞 Retired Ninja 11/8/2023
消息“警告:函数的隐式声明”和“函数的隐式声明”是什么意思? 也可能有所帮助。
0赞 Rodion Iskhakov 11/8/2023
@RetiredNinja,啊,我忘了原型......谢谢,如果你把你的评论写成答案,我会接受的。
2赞 user3386109 11/8/2023
要正确声明一个不带参数的函数,请使用关键字,例如 和。仅允许使用空参数列表,以便向后兼容 C89 代码。不应在新代码中使用空参数列表。voidvoid print_value(void);int main(void)()
1赞 Jonathan Leffler 11/8/2023
[...继续...]声明函数时,using 表示对参数列表一无所知(除了它不是一个签名结尾的可变函数——那些必须用完整的原型声明),同样需要注意的是,规则会随着 C23 或更高版本而改变。在 C23 中,C 终于赶上了 C++——K&R 风格的非原型函数定义不再有效,参数列表中的空括号表示“没有参数”。我认为使用它是安全的还需要一段时间——我将再使用十年左右。function(), ...)(void)

答:

2赞 Vlad from Moscow 11/8/2023 #1

根据第一条编译器消息,编译器在编译模块时不知道模块中使用的函数是如何声明的。print_value()main.c

#include <stdlib.h>
//#include "secondary.c"

int main ()
{
         extern int my_var;

         my_var = 123;
         print_value ();
         exit (0);
}

使用函数声明(原型)创建标头,例如

void print_value( void );

并在两个模块中包含标头。

至于第二条消息,那么在包含 之后,您在两个模块和 .不要将 c midules 彼此包含。secondary.cmain.cmain.csecondary.c

需要注意的是,根据 C 标准,不带参数的函数应声明为main

int main( void )

还有这个声明

exit (0);

是多余的。删除它。

还要记住,根据 C23 标准,您不能使用没有函数原型的函数,因为在 C23 标准之前是允许的。

评论

0赞 Rodion Iskhakov 11/8/2023
我真的应该将关键字添加为函数的参数吗?没有它,它仍然运行良好,并且不会发送任何警告。有什么客观原因吗?我为什么要删除该声明?我读到这句话指定程序正常结束,一切正常。该函数还执行一些整理任务,例如关闭打开的文件。使用 or 也是由 GNU 编码标准指定的。voidexit (0);exitexit(0);return 0;
0赞 Vlad from Moscow 11/8/2023
@RodionIskhakov 正如我所写的,新的 C23 标准不允许此类声明。至于第二个问题,如果控件达到函数 main 的右大括号,则效果与显式放置语句返回 0 相同;
0赞 Rodion Iskhakov 11/8/2023
我检查了维基百科上的C23标准页面,发现以下行:“原型中没有列出参数的函数被理解为不带参数(参见删除K&R函数声明)”void foo()
0赞 Vlad from Moscow 11/8/2023
@RodionIskhakov void foo();不是函数原型。关于它的参数一无所知。
2赞 Vlad from Moscow 11/8/2023
@RodionIskhakov 摘自C标准《5.1.2.2.3 程序终止 1 如果 main 函数的返回类型是与 int 兼容的类型,则从初始调用返回 main 函数等效于调用退出函数,并将 main 函数返回的值作为其参数;11) 到达终止主函数的 } 返回值 0。如果返回类型与 int 不兼容,则返回到主机环境的终止状态未指定。