实际上我是用多个文件编译的。以下是文件:
文件main.c-->
#include <stdio.h>
void foo3(void)
{
printf("INSIDE foo3 functionn");
}
int main()
{
foo1();
foo2();
foo3();
}
文件1.c-->
#include <stdio.h>
void foo1(void)
{
printf("INSIDE foo1 functionn");
}
文件2.c-->
#include <stdio.h>
void foo2(void)
{
printf("INSIDE foo2 functionn");
}
现在我使用gcc编译如下-->
gcc 1.c 2.c main.c -o main
以下是输出-->
INSIDE foo1 function
INSIDE foo2 function
INSIDE foo3 function
我的疑问是,如果main.c
中没有声明foo1()
和foo2()
,main
()怎么会调用它们。但现在,如果我把main.c改为如下(在main()
之后写foo3()
的定义):
已编辑main.c-->
#include <stdio.h>
int main()
{
foo1();
foo2();
foo3();
}
void foo3(void)
{
printf("INSIDE foo3 functionn");
}
然后如果我编译,我会得到这个错误:
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();
^
为什么在CCD_ 7和CCD_。提前谢谢。
我的疑问是,当
main.c
中没有声明foo1()
和foo2()
时,main()
怎么能调用它们
因为GCC编译器默认使用旧的ANSI C(又名C89)语言,其中允许使用未声明的函数,并且默认给出int
结果。
尝试调用编译器,例如
gcc -std=c99 -Wall -g -c main.c
或者(如果你想一次编译所有文件)
gcc -std=c99 -Wall -g 1.c 2.c main.c -o main
您可以要求使用gcc -flto
而不是gcc
进行链接时间过程间优化,使用最近的GCC,例如2014年9月的GCC 4.9。
这将需要一个符合C99的源代码,其中应该声明所有函数。-Wall
要求(几乎)所有警告。-g
选项生成一个可调试的对象代码(或可执行的最后一个命令同时编译所有文件)。
在您编辑的main.c
中,当第一次出现foo3
(在main
内)时,编译器猜测它是一个返回int
的函数。当编译器看到foo3
的定义时,它会正确地抱怨。
您可以将-Wstrict-prototypes
警告选项用于gcc
(但它是由-Wall
暗示的,我一直建议使用它)。
在链接时,C函数的类型(和签名)并不重要。链接器只是使用名称来完成它的工作(但C++使用名称篡改)。当然,用错误的参数或结果调用函数是未定义的行为。
良好的常规做法是使用一个公共头文件来声明所有使用的和公共的函数和类型(以及常量),并将该头文件包含在源文件中(这样可以避免多次复制和粘贴这些声明)。所以你会有一个像一样的新头文件myheader.h
// 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"
(在那里的#include <stdio.h>
指令之后)。注意MY_HEADER_INCLUDED
的包含保护技巧。
在实践中,头文件通常包含解释程序的API的注释。
还可以了解GNU make。它将简化多源代码文件程序的构建(您只需通过运行make
进行编译和构建)。参见Makefile
的这个和那个示例。理解C预处理是C编译的第一阶段。