实际上我正在使用多个文件进行编译。以下是文件:
文件main.c - >
#include <stdio.h>
void foo3(void)
{
printf("INSIDE foo3 function\n");
}
int main()
{
foo1();
foo2();
foo3();
}
档案1.c - &gt;
#include <stdio.h>
void foo1(void)
{
printf("INSIDE foo1 function\n");
}
文件2.c - &gt;
#include <stdio.h>
void foo2(void)
{
printf("INSIDE foo2 function\n");
}
现在我使用gcc编译如下 - &gt;
gcc 1.c 2.c main.c -o main
以下是输出 - &gt;
INSIDE foo1 function
INSIDE foo2 function
INSIDE foo3 function
我怀疑main
()如何在foo1()
中宣布foo2()
时调用main.c
和foo3()
。但是现在如果我按照以下方式更改main.c(在main()
之后写#include <stdio.h>
int main()
{
foo1();
foo2();
foo3();
}
void foo3(void)
{
printf("INSIDE foo3 function\n");
}
的定义),就像这样:
编辑main.c - &gt;
main.c:9:6: warning: conflicting types for ‘foo3’ [enabled by default]
void foo3(void)
^
main.c:6:2: note: previous implicit declaration of ‘foo3’ was here
foo3();
^
然后如果我编译我得到这个错误:
foo1()
为什么在foo2()
和{{1}}的情况下,此错误未在前面显示。先感谢您。
答案 0 :(得分:1)
我怀疑当
中没有宣布main()
foo1()
foo2()
和main.c
时,int
如何调用gcc -std=c99 -Wall -g -c main.c
和gcc -std=c99 -Wall -g 1.c 2.c main.c -o main
因为GCC编译器默认使用旧的ANSI C(也称为C89)语言,允许使用未声明的函数,默认为提供gcc -flto
结果。
尝试调用编译器,例如
gcc
或(如果您想一次编译所有文件)
-Wall
您可以使用最近的 link time interprocedural optimizations与-g
而不是main.c
要求GCC,例如GCC 4.9于2014年9月举行。
这需要符合C99条件的源代码,其中应声明所有函数。
foo3
要求(几乎)所有警告。 main
选项生成可调试的目标代码(或最后一个命令的可执行文件,一次编译所有文件)。
在您编辑的int
遇到foo3
第一次出现(-Wstrict-prototypes
内)时,编译器会猜测它是一个返回gcc
的函数。当编译器看到-Wall
的定义时,它会正确地抱怨。
您可以使用myheader.h
警告option至// file myheader.h
#ifndef MY_HEADER_INCLUDED
#define MY_HEADER_INCLUDED
void foo1(void);
void foo2(void);
void foo3(void);
#endif /*MY_HEADER_INCLUDED*/
(但我始终建议使用#include "myheader.h"
隐含此警告。)
在链接时,C函数的类型(和签名)无关紧要。链接器只使用name来完成它的工作(但是C ++使用name mangling)。当然,使用不正确的参数或结果调用函数是undefined behavior。
良好的传统做法是有一个公共头文件,声明源文件中所有已使用和公共函数和类型(和常量)和include头文件(这样可以避免必须多次复制和粘贴这些声明)。所以你应该有一个新的头文件#include <stdio.h>
,如
MY_HEADER_INCLUDED
并且您将在所有源文件中添加make
(在Makefile
指令之后)。请注意{{1}}的{{3}}技巧。
实际上,标题文件通常包含解释程序include guard的注释。
另请了解API。它将简化多源代码文件程序的构建(您只需通过运行{{1}}进行编译和构建)。请参阅{{1}}的{{3}}和GNU make示例。理解this是C编译的第一阶段。