I'm learning C, but i have a long experience with higher level programming languages like Java.
我正在学习C语言,但我有很长时间使用Java等高级编程语言。
I was reading about header files so i was playing around with them, however I noticed that I could call a function from another file without #including it (it's in the same directory), how is that possible ?! Is it the make file, linker that is configured that way or what ?
我正在阅读关于头文件的内容,所以我在和他们一起玩,但是我注意到我可以从另一个文件中调用一个函数,而不包括它(它在同一个目录中),这怎么可能呢?是这样配置的make文件、链接器还是什么?
We have two files
我们有两个文件
main.c
add.c
main.c calls the function add(int x,int y)
from add add.c, but I mistakenly compiled before #including add.c and it worked ! What makes it more confusing is that when i #include add.c, it gives a multiple-definition error on function add
主要。c从add add.c.调用函数add(int x,int y),但是我在# include addc之前编译错误,它工作了!更让人困惑的是,当我#include addc时,它会在函数add上出现多定义错误
4 个解决方案
#1
79
There's a few different things going on here. First I'll go over how basic compilation of multiple files works.
这里发生了一些不同的事情。首先,我将介绍如何基本地编译多个文件。
If you have multiple files, the important thing is the difference between the declaration and definition of a function. The definition is probably what you are used to when defining functions: You write up the contents of the function, like
如果有多个文件,重要的是函数的声明和定义之间的区别。定义可能就是定义函数时所使用的定义:编写函数的内容,比如
int square(int i) {
return i*i;
}
The declaration, on the other hand, lets you declare to the compiler that you know a function exists, but you don't tell the compiler what it is. For example, you could write
另一方面,声明允许您向编译器声明您知道一个函数存在,但不告诉编译器它是什么。例如,你可以写
int square(int i);
And the compiler would expect that the function "square" is defined elsewhere.
编译器会期望函数“square”在其他地方被定义。
Now, if you have two different files that you want to interoperate (for example, let's say that the function "square" is defined in add.c, and you want to call square(10) in main.c), you need to do both a definition and a declaration. First, you define square in add.c. Then, you declare it at the beginning of main.c. This let's the compiler know when it is compiling main.c that there is a function "square" which is defined elsewhere. Now, you need to compile both main.c and add.c into object files. You can do this by calling
现在,如果有两个不同的文件需要互操作(例如,假设函数“square”在addc中定义,并希望在main.c中调用square(10)),那么需要同时执行定义和声明。首先,在addc中定义square。然后,您在main.c开头声明它。这让编译器知道它何时编译main。有一个函数“square”,它在其他地方被定义。现在,您需要同时编译这两个main。将c和addc转换为目标文件。你可以打电话来。
gcc -c main.c
gcc -c add.c
This will produce the files main.o and add.o. They contain the compiled functions, but are not quite executable. The important thing to understand here is that main.o is "incomplete" in a sense. When compiling main.o, you told it that the function "square" exists, but the function "square" is not defined inside main.o. Thus main.o has a sort of "dangling reference" to the function "square". It won't compile into a full program unless you combine it with another .o (or a .so or .a) file which contains a definition of "square". If you just try to link main.o into a program, i.e.
这将生成主文件。o和add.o。它们包含已编译的函数,但不是完全可执行的。这里要理解的最重要的一点是这个主题。o在某种意义上是“不完整的”。当编译主要。o,您告诉它函数“square”存在,但是main.o中没有定义函数“square”。因此主要。o对函数“square”有一种“悬浮引用”。它不会编译成一个完整的程序,除非您将它与另一个。o(或一个so或a)文件合并,该文件包含“square”的定义。如果你尝试链接main。o进入一个程序,即
gcc -o executable main.o
You will get an error, because the compiler will try to resolve the dangling reference to the function "square", but wont find any definition for it. However, if you include add.o when linking (linking is the process of resolving all these references to undefined functions while converting .o files to executables or .so files), then there won't be any problem. i.e.
您将会得到一个错误,因为编译器将试图解决悬空引用的函数“square”,但不会找到它的任何定义。但是,如果在链接时包含add.o(链接是在将.o文件转换为可执行文件或文件)时,将所有这些引用解析为未定义的函数的过程,那么就不会有任何问题。即。
gcc -o executable main.o add.o
So that's how to functionally use functions across C files, but stylistically, what I just showed you is "not the right way". The only reason I did is because I think it will better help you understand what's going on, rather than relying on "#include magic". Now, you might have noticed before that things get a little messy if you have to redeclare every function you want to use at the top of main.c This is why often C programs use helper files called "headers" which have a .h extension. The idea of a header is that it contains just the declarations of the functions, without their definitions. This way, in order to compile a program using functions defined in add.c, you need not manually declare every function you are using, nor need you #include the entire add.c file in your code. Instead, you can #include add.h, which simply contains the declarations of all the functions of add.c.
这就是如何在C文件中功能性地使用函数,但是在文体上,我刚才给你们展示的不是正确的方法。我这么做的唯一原因是,我认为它能更好地帮助你理解正在发生的事情,而不是依赖“#include magic”。现在,你可能已经注意到,如果你必须重新声明你想在main顶部使用的每个函数,事情会变得有点混乱。这就是为什么c程序经常使用称为“header”的助手文件,这些文件的扩展名是.h。header的概念是,它只包含函数的声明,没有定义。这样,为了使用在addc中定义的函数来编译程序,您不需要手动声明您正在使用的每个函数,也不需要在代码中包含整个addc文件。相反,您可以#include .h,它只包含addc的所有函数的声明。
Now, a refresher on #include: #include simply copies the contents of one file directly into another. So, for example, the code
现在,复习一下#include: #include,直接将一个文件的内容复制到另一个文件中。例如,代码
abc
#include "wtf.txt"
def
is exactly equivalent to
是完全等价的
abc
hello world
def
assuming that wtf.txt contains the text "hello world".
假设wtf。txt包含文本“hello world”。
So, if we put all the declarations of add.c in add.h (i.e.
因此,如果我们把addc的所有声明放在add。h中(即。
int square(int i);
and then at the top of main.c, we write
然后在main的顶部。c,我们写
#include "add.h"
This is functionally the same as if we had just manually declared the function "square" at the top of main.c.
这在功能上与我们刚才手动声明main.c顶部的函数“square”相同。
So the general idea of using headers is that you can have a special file that automatically declares all the functions you need by just #including it.
因此,使用header的一般思想是,你可以有一个特殊的文件,通过# include它自动声明所有你需要的函数。
However, headers also have one more common use. Let's suppose that main.c uses functions from 50 different files. The top of main.c would look like:
但是,header还有一个更常见的用途。主要假设。c使用来自50个不同文件的函数。主要的顶端。c的样子:
#include "add.h"
#include "divide.h"
#include "multiply.h"
#include "eat-pie.h"
...
Instead, people often move all those #includes to the main.h header file, and just #include main.h from main.c. In this case, the header file serves two purposes. It declares the functions in main.c for use when included by other files, and it includes all of the dependencies of main.c when included from main.c. Using it this way also allows chains of dependencies. If you #include add.h, not only do you get the functions defined in add.c, but you also implicitly get any functions which add.c uses, and any functions they use, and so on.
相反,人们通常把所有这些#include移到main。h头文件,只有#include main。从c h。在这种情况下,头文件有两个用途。它主要声明函数。c用于其他文件的使用,并且包含main的所有依赖项。c.从main.c中包含。以这种方式使用它还允许依赖链。如果#include add.h,不仅会得到在addc中定义的函数,还会隐式地得到addc使用的任何函数,以及它们使用的任何函数,等等。
Also, more subtly, #including a header file from it's own .c file implicitly checks for errors you make. If for example, you accidentally defined square as
另外,更微妙的是,#包含来自它自己的.c文件的头文件,它隐式地检查您所犯的错误。例如,你不小心把square定义为
double square(int i);
in add.h, you normally might not realize until you were linking that main.o is looking for one definition of square, and add.o is providing another, incompatible one. This will cause you to get errors when linking, so you won't realize the mistake until later in the build process. However, if you #include add.h from add.c, to the compiler, your file looks like
在add.h中,通常情况下,你可能没有意识到,直到你把那个main连接起来。o寻找平方的一个定义,而ad。o提供了另一个不相容的定义。这将导致在链接时出现错误,因此直到构建过程的稍后阶段您才会意识到错误。但是,如果您将addc中的add.h包含到编译器中,那么您的文件看起来是这样的
#include "add.h"
int square(int i) {
return i*i;
}
which after processing the #include statement will look like
处理完#include语句后,会是什么样子
double square(int i);
int square(int i) {
return i*i;
}
Which the compiler will notice when compiling add.c, and tell you about. Effectively, including your own header in this way prevents you from falsely advertising to other files the type of the functions you are providing.
编译器在编译addc时会注意到,并告诉你。有效地,包括你自己的头,以这种方式防止你虚假广告到其他文件类型的功能你提供。
Why you can use a function without ever declaring it
为什么你可以使用一个函数而不用声明它
As you have noticed, in some cases you can actually use a function without every declaring it or #including any file which declares it. This is stupid, and everyone agrees that this is stupid. However, it is a legacy feature of the C programming language (and C compilers) that if you use a function without declaring it first, it just assumes that it is a function returning type "int". So in effect, using a function is implicitly declaring that function as a function which returns "int" if it is not already declared. It's very strange behavior if you think about it, and the compiler should warn you if you it doing that behavior.
正如您所注意到的,在某些情况下,您实际上可以使用一个函数,而不必声明它或#,包括声明它的任何文件。这是愚蠢的,每个人都认为这是愚蠢的。但是,C编程语言(和C编译器)的一个遗留特性是,如果您使用一个函数而没有首先声明它,那么它就假定它是返回类型为“int”的函数。因此,实际上,使用函数是在隐式地声明该函数,如果该函数尚未声明,则返回“int”。如果你仔细想想,这是非常奇怪的行为,如果你这样做,编译器应该警告你。
Header Guards
头警卫
One other common practice is the use of "Header Guards". To explain header guards, let's look at a possible problem. Let's say that we have two files: herp.c, and derp.c, and they both want to use functions contained in each other. Following the above guidelines, you might have a herp.h with the line
另一种常见的做法是使用“头护”。为了解释页眉保护,让我们看看一个可能的问题。假设我们有两个文件:herp。c,derp。它们都希望使用相互包含的函数。按照上面的指导方针,你可能有一个herp。h的线
#include "derp.h"
and a derp.h with the line
和一个derp。h的线
#include "herp.h"
Now, if you think about it, #include "derp.h" will be converted to the contents of derp.h, which in turn contains the line #include "herp.h", which will be converted to the contents of herp.h, and that contains... and so on, so the compiler will go on forever just expanding the includes. Similarly, if main.h #includes both herp.h and derp.h, and both herp.h and derp.h include add.h, we see that in main.h, we end up with two copies of add.h, one as a result of #including herp.h, and one as a result of including derp.h. So, the solution? A "Header guard", i.e. a piece of code which prevents any header from being #included twice. For add.h, for example, the normal way to do this is:
现在,如果你仔细想想,#include“derp”。h"将被转换为derp的内容。h,它依次包含行#包含“herp”。h"将转换为herp的内容。h,包含…这样,编译器就会不断地扩展include。类似地,如果主要。h #包括爬虫。h和derp。h,爬虫。h和derp。h包含ad。h,我们主要看到了。h,我们最终得到了两份add.h,一份是由于#包含herp。h,由于包括了derp。h。那么,解决方案?一种“报头保护”,即防止任何报头被包含两次的一段代码。例如,对于add.h,通常的做法是:
#ifndef ADD_H
#define ADD_H
int sqrt(int i);
...
#endif
This piece of code is essentially telling the preprocessor (the part of the compiler which handles all of the "#XXX" statements) to check if "ADD_H" is already defined. If it isn't (ifndef) then it first defines "ADD_H" (in this context, ADD_H doesn't have to be defined as anything, it is just a boolean which is either defined or not), and then defines the rest of the contents of the header. However, if ADD_H is already defined, then #including this file will do nothing, because there is nothing outside of the #ifndef block. So the idea is that only the first time it is included in any given file will it actually add any text to that file. After that, #including it will not add any additional text to your file. ADD_H is just an arbitrary symbol you choose to keep track of whether add.h has been included yet. For every header, you use a different symbol to keep track of whether it has been included yet or not. For example, herp.h would probably use HERP_H instead of ADD_H. Using a "header guard" will fix any of the problems I listed above, where you have duplicate copies of a file included, or an infinite loop of #includes.
这段代码实质上是告诉预处理器(处理所有“#XXX”语句的编译器的一部分)检查“ADD_H”是否已经定义。如果它不是(ifndef),那么它首先定义“ADD_H”(在这个上下文中,ADD_H不必定义为任何东西,它只是一个布尔值,可以定义也可以不定义),然后定义头的其余内容。但是,如果已经定义了ADD_H,那么包含这个文件的#将不起作用,因为在#ifndef块之外没有任何东西。所以这个想法是,只有第一次它被包含在任何给定的文件中它实际上会添加任何文本到那个文件。之后,# include将不会向文件中添加任何其他文本。ADD_H只是一个任意的符号,您可以选择它来跟踪是否已经包含了ad .h。对于每个header,您使用不同的符号来跟踪它是否已经包含。例如,爬虫。h可能会用HERP_H代替ADD_H。使用“header guard”可以修复上面列出的任何问题,比如包含文件的副本,或者包含#include的无限循环。
#2
4
The problem is that you shouldn't be #include
ing a .c file.
问题是您不应该包含.c文件。
To use a function in another file, you need to declare it. Usually, every .c file (except main.c) has an associated header (.h) file that properly declares all the functions defined in the .c file. You can declare as many times as you want (so long as all the declarations are identical), but there can only be one definition.
要在另一个文件中使用函数,需要声明它。通常,每个.c文件(main.c除外)都有一个关联的头文件(.h),它正确地声明.c文件中定义的所有函数。您可以声明任意次数(只要所有的声明都是相同的),但是只能有一个定义。
What happens when you #include "add.c"
is that the text of add.c is included in main.c, giving main.c a definition (and, as a side-effect, a declaration) of add
. Then, when you compile add.c on it's own, that creates another definition of add
. Thus, there are two definitons of the function, and the compiler freaks out because it doesn't know which one to use.
当您#include“addc”时,会发生的事情是addc的文本包含在main中。c,给主。c是add的一个定义(还有一个副作用,一个声明),然后,当你自己编译addc时,就会创建add的另一个定义。
If you change it to #include "add.h"
, where add.h looks something like this:
如果你将它改为#include "add.h",其中add.h看起来是这样的:
#ifndef ADD_H
#define ADD_H
extern int add(int x, int y);
#endif /* ADD_H - Google "include guard" for more info about this trickery */
then main.c has a declaration of add
and can use the function, but the definition of add
is quite firmly only in the add.c file, and so it only exists once, and so it will compile properly.
那么主要。c有一个add的声明,并且可以使用这个函数,但是add的定义仅仅是在addc文件中,所以它只存在一次,所以它会正确地编译。
#3
2
Here is a simple example of calling a function from different c program
下面是一个调用来自不同c程序的函数的简单示例
let me name the main program as main.c and the program that holds the function as function.c for the function.c I am creating the header file called function.h
我把主程序命名为main。c和将函数保存为函数的程序。c函数。我正在创建名为function.h的头文件。
main.c
c
#include"function.h"
int main()
{
int a = sum(1,2);
return a;
}
function.c
function.c
int function(int a,int b)
{
return a+b;
}
function.h
function.h
int function(int,int);
To compile use the command given below
要编译,请使用下面给出的命令
g++ main.c function.c -o main
g++主要。c函数。c - o主要
Here the detailed explanation. In the main program I have called the function to sum 2 numbers. The values 1 and 2 in the main program was feed to the function in the function.c through the header function.h which holds the access point or the bridge to the function.c
这里的详细解释。在主程序中,我调用函数求和两个数。主程序中的值1和2被提供给函数中的函数。c通过header函数。h,它保存了访问点或功能的桥
For more details you can check the links given below
有关更多细节,请查看下面给出的链接
http://www.cplusplus.com/forum/beginner/34691/
http://www.cplusplus.com/forum/beginner/34691/
https://social.msdn.microsoft.com/Forums/en-US/4ea70f43-a0d5-43f8-8e24-78e90f208110/calling-a-function-in-a-file-from-another-file?forum=winembplatdev
https://social.msdn.microsoft.com/forums/en us/4ea70f43 - a0d5 - 43 - f8 - 8 e24 - 78 e90f208110/calling - a -功能- - -文件从file?forum=winembplatdev——另一个
Add a print statement to check the result or use echo $? after execution of the file main
添加一个打印语句来检查结果或使用echo $?执行后的文件主
#4
1
You're able to call it because a declaration isn't necessary to make a call in C. The return type however is unknown, and so will default to int
. This is possible in part due to the default calling convention in C, and the default promotion of types to at least int
precision.
你可以叫它因为声明没有必要打电话但是在C .返回类型是未知的,所以将默认为int。这可能部分由于默认的调用协定在C语言中,至少和默认推广类型int精度。
If you include a header that defines the function you are calling, the compiler is able to check that calls to the function have the correct number and type of arguments.
如果包含一个定义要调用的函数的头,编译器可以检查对函数的调用是否有正确的参数数量和类型。
If you include function definitions, they will be exported unless you specify their storage with static
. Since you're also compiling and linking add.c
, you can't add this since then either neither or both of your object files will then be exporting add
.
如果包含函数定义,那么它们将被导出,除非您使用静态方法指定它们的存储。由于您也在编译和链接addc,所以您不能添加这个,因为那时您的两个对象文件都不会导出添加。
If you want to simply include all your functions, best to put their definitions into headers, and sprinkle storage specifiers on them.
如果您只想包含所有的函数,那么最好将它们的定义放在header中,并在它们上面撒上存储说明符。
#1
79
There's a few different things going on here. First I'll go over how basic compilation of multiple files works.
这里发生了一些不同的事情。首先,我将介绍如何基本地编译多个文件。
If you have multiple files, the important thing is the difference between the declaration and definition of a function. The definition is probably what you are used to when defining functions: You write up the contents of the function, like
如果有多个文件,重要的是函数的声明和定义之间的区别。定义可能就是定义函数时所使用的定义:编写函数的内容,比如
int square(int i) {
return i*i;
}
The declaration, on the other hand, lets you declare to the compiler that you know a function exists, but you don't tell the compiler what it is. For example, you could write
另一方面,声明允许您向编译器声明您知道一个函数存在,但不告诉编译器它是什么。例如,你可以写
int square(int i);
And the compiler would expect that the function "square" is defined elsewhere.
编译器会期望函数“square”在其他地方被定义。
Now, if you have two different files that you want to interoperate (for example, let's say that the function "square" is defined in add.c, and you want to call square(10) in main.c), you need to do both a definition and a declaration. First, you define square in add.c. Then, you declare it at the beginning of main.c. This let's the compiler know when it is compiling main.c that there is a function "square" which is defined elsewhere. Now, you need to compile both main.c and add.c into object files. You can do this by calling
现在,如果有两个不同的文件需要互操作(例如,假设函数“square”在addc中定义,并希望在main.c中调用square(10)),那么需要同时执行定义和声明。首先,在addc中定义square。然后,您在main.c开头声明它。这让编译器知道它何时编译main。有一个函数“square”,它在其他地方被定义。现在,您需要同时编译这两个main。将c和addc转换为目标文件。你可以打电话来。
gcc -c main.c
gcc -c add.c
This will produce the files main.o and add.o. They contain the compiled functions, but are not quite executable. The important thing to understand here is that main.o is "incomplete" in a sense. When compiling main.o, you told it that the function "square" exists, but the function "square" is not defined inside main.o. Thus main.o has a sort of "dangling reference" to the function "square". It won't compile into a full program unless you combine it with another .o (or a .so or .a) file which contains a definition of "square". If you just try to link main.o into a program, i.e.
这将生成主文件。o和add.o。它们包含已编译的函数,但不是完全可执行的。这里要理解的最重要的一点是这个主题。o在某种意义上是“不完整的”。当编译主要。o,您告诉它函数“square”存在,但是main.o中没有定义函数“square”。因此主要。o对函数“square”有一种“悬浮引用”。它不会编译成一个完整的程序,除非您将它与另一个。o(或一个so或a)文件合并,该文件包含“square”的定义。如果你尝试链接main。o进入一个程序,即
gcc -o executable main.o
You will get an error, because the compiler will try to resolve the dangling reference to the function "square", but wont find any definition for it. However, if you include add.o when linking (linking is the process of resolving all these references to undefined functions while converting .o files to executables or .so files), then there won't be any problem. i.e.
您将会得到一个错误,因为编译器将试图解决悬空引用的函数“square”,但不会找到它的任何定义。但是,如果在链接时包含add.o(链接是在将.o文件转换为可执行文件或文件)时,将所有这些引用解析为未定义的函数的过程,那么就不会有任何问题。即。
gcc -o executable main.o add.o
So that's how to functionally use functions across C files, but stylistically, what I just showed you is "not the right way". The only reason I did is because I think it will better help you understand what's going on, rather than relying on "#include magic". Now, you might have noticed before that things get a little messy if you have to redeclare every function you want to use at the top of main.c This is why often C programs use helper files called "headers" which have a .h extension. The idea of a header is that it contains just the declarations of the functions, without their definitions. This way, in order to compile a program using functions defined in add.c, you need not manually declare every function you are using, nor need you #include the entire add.c file in your code. Instead, you can #include add.h, which simply contains the declarations of all the functions of add.c.
这就是如何在C文件中功能性地使用函数,但是在文体上,我刚才给你们展示的不是正确的方法。我这么做的唯一原因是,我认为它能更好地帮助你理解正在发生的事情,而不是依赖“#include magic”。现在,你可能已经注意到,如果你必须重新声明你想在main顶部使用的每个函数,事情会变得有点混乱。这就是为什么c程序经常使用称为“header”的助手文件,这些文件的扩展名是.h。header的概念是,它只包含函数的声明,没有定义。这样,为了使用在addc中定义的函数来编译程序,您不需要手动声明您正在使用的每个函数,也不需要在代码中包含整个addc文件。相反,您可以#include .h,它只包含addc的所有函数的声明。
Now, a refresher on #include: #include simply copies the contents of one file directly into another. So, for example, the code
现在,复习一下#include: #include,直接将一个文件的内容复制到另一个文件中。例如,代码
abc
#include "wtf.txt"
def
is exactly equivalent to
是完全等价的
abc
hello world
def
assuming that wtf.txt contains the text "hello world".
假设wtf。txt包含文本“hello world”。
So, if we put all the declarations of add.c in add.h (i.e.
因此,如果我们把addc的所有声明放在add。h中(即。
int square(int i);
and then at the top of main.c, we write
然后在main的顶部。c,我们写
#include "add.h"
This is functionally the same as if we had just manually declared the function "square" at the top of main.c.
这在功能上与我们刚才手动声明main.c顶部的函数“square”相同。
So the general idea of using headers is that you can have a special file that automatically declares all the functions you need by just #including it.
因此,使用header的一般思想是,你可以有一个特殊的文件,通过# include它自动声明所有你需要的函数。
However, headers also have one more common use. Let's suppose that main.c uses functions from 50 different files. The top of main.c would look like:
但是,header还有一个更常见的用途。主要假设。c使用来自50个不同文件的函数。主要的顶端。c的样子:
#include "add.h"
#include "divide.h"
#include "multiply.h"
#include "eat-pie.h"
...
Instead, people often move all those #includes to the main.h header file, and just #include main.h from main.c. In this case, the header file serves two purposes. It declares the functions in main.c for use when included by other files, and it includes all of the dependencies of main.c when included from main.c. Using it this way also allows chains of dependencies. If you #include add.h, not only do you get the functions defined in add.c, but you also implicitly get any functions which add.c uses, and any functions they use, and so on.
相反,人们通常把所有这些#include移到main。h头文件,只有#include main。从c h。在这种情况下,头文件有两个用途。它主要声明函数。c用于其他文件的使用,并且包含main的所有依赖项。c.从main.c中包含。以这种方式使用它还允许依赖链。如果#include add.h,不仅会得到在addc中定义的函数,还会隐式地得到addc使用的任何函数,以及它们使用的任何函数,等等。
Also, more subtly, #including a header file from it's own .c file implicitly checks for errors you make. If for example, you accidentally defined square as
另外,更微妙的是,#包含来自它自己的.c文件的头文件,它隐式地检查您所犯的错误。例如,你不小心把square定义为
double square(int i);
in add.h, you normally might not realize until you were linking that main.o is looking for one definition of square, and add.o is providing another, incompatible one. This will cause you to get errors when linking, so you won't realize the mistake until later in the build process. However, if you #include add.h from add.c, to the compiler, your file looks like
在add.h中,通常情况下,你可能没有意识到,直到你把那个main连接起来。o寻找平方的一个定义,而ad。o提供了另一个不相容的定义。这将导致在链接时出现错误,因此直到构建过程的稍后阶段您才会意识到错误。但是,如果您将addc中的add.h包含到编译器中,那么您的文件看起来是这样的
#include "add.h"
int square(int i) {
return i*i;
}
which after processing the #include statement will look like
处理完#include语句后,会是什么样子
double square(int i);
int square(int i) {
return i*i;
}
Which the compiler will notice when compiling add.c, and tell you about. Effectively, including your own header in this way prevents you from falsely advertising to other files the type of the functions you are providing.
编译器在编译addc时会注意到,并告诉你。有效地,包括你自己的头,以这种方式防止你虚假广告到其他文件类型的功能你提供。
Why you can use a function without ever declaring it
为什么你可以使用一个函数而不用声明它
As you have noticed, in some cases you can actually use a function without every declaring it or #including any file which declares it. This is stupid, and everyone agrees that this is stupid. However, it is a legacy feature of the C programming language (and C compilers) that if you use a function without declaring it first, it just assumes that it is a function returning type "int". So in effect, using a function is implicitly declaring that function as a function which returns "int" if it is not already declared. It's very strange behavior if you think about it, and the compiler should warn you if you it doing that behavior.
正如您所注意到的,在某些情况下,您实际上可以使用一个函数,而不必声明它或#,包括声明它的任何文件。这是愚蠢的,每个人都认为这是愚蠢的。但是,C编程语言(和C编译器)的一个遗留特性是,如果您使用一个函数而没有首先声明它,那么它就假定它是返回类型为“int”的函数。因此,实际上,使用函数是在隐式地声明该函数,如果该函数尚未声明,则返回“int”。如果你仔细想想,这是非常奇怪的行为,如果你这样做,编译器应该警告你。
Header Guards
头警卫
One other common practice is the use of "Header Guards". To explain header guards, let's look at a possible problem. Let's say that we have two files: herp.c, and derp.c, and they both want to use functions contained in each other. Following the above guidelines, you might have a herp.h with the line
另一种常见的做法是使用“头护”。为了解释页眉保护,让我们看看一个可能的问题。假设我们有两个文件:herp。c,derp。它们都希望使用相互包含的函数。按照上面的指导方针,你可能有一个herp。h的线
#include "derp.h"
and a derp.h with the line
和一个derp。h的线
#include "herp.h"
Now, if you think about it, #include "derp.h" will be converted to the contents of derp.h, which in turn contains the line #include "herp.h", which will be converted to the contents of herp.h, and that contains... and so on, so the compiler will go on forever just expanding the includes. Similarly, if main.h #includes both herp.h and derp.h, and both herp.h and derp.h include add.h, we see that in main.h, we end up with two copies of add.h, one as a result of #including herp.h, and one as a result of including derp.h. So, the solution? A "Header guard", i.e. a piece of code which prevents any header from being #included twice. For add.h, for example, the normal way to do this is:
现在,如果你仔细想想,#include“derp”。h"将被转换为derp的内容。h,它依次包含行#包含“herp”。h"将转换为herp的内容。h,包含…这样,编译器就会不断地扩展include。类似地,如果主要。h #包括爬虫。h和derp。h,爬虫。h和derp。h包含ad。h,我们主要看到了。h,我们最终得到了两份add.h,一份是由于#包含herp。h,由于包括了derp。h。那么,解决方案?一种“报头保护”,即防止任何报头被包含两次的一段代码。例如,对于add.h,通常的做法是:
#ifndef ADD_H
#define ADD_H
int sqrt(int i);
...
#endif
This piece of code is essentially telling the preprocessor (the part of the compiler which handles all of the "#XXX" statements) to check if "ADD_H" is already defined. If it isn't (ifndef) then it first defines "ADD_H" (in this context, ADD_H doesn't have to be defined as anything, it is just a boolean which is either defined or not), and then defines the rest of the contents of the header. However, if ADD_H is already defined, then #including this file will do nothing, because there is nothing outside of the #ifndef block. So the idea is that only the first time it is included in any given file will it actually add any text to that file. After that, #including it will not add any additional text to your file. ADD_H is just an arbitrary symbol you choose to keep track of whether add.h has been included yet. For every header, you use a different symbol to keep track of whether it has been included yet or not. For example, herp.h would probably use HERP_H instead of ADD_H. Using a "header guard" will fix any of the problems I listed above, where you have duplicate copies of a file included, or an infinite loop of #includes.
这段代码实质上是告诉预处理器(处理所有“#XXX”语句的编译器的一部分)检查“ADD_H”是否已经定义。如果它不是(ifndef),那么它首先定义“ADD_H”(在这个上下文中,ADD_H不必定义为任何东西,它只是一个布尔值,可以定义也可以不定义),然后定义头的其余内容。但是,如果已经定义了ADD_H,那么包含这个文件的#将不起作用,因为在#ifndef块之外没有任何东西。所以这个想法是,只有第一次它被包含在任何给定的文件中它实际上会添加任何文本到那个文件。之后,# include将不会向文件中添加任何其他文本。ADD_H只是一个任意的符号,您可以选择它来跟踪是否已经包含了ad .h。对于每个header,您使用不同的符号来跟踪它是否已经包含。例如,爬虫。h可能会用HERP_H代替ADD_H。使用“header guard”可以修复上面列出的任何问题,比如包含文件的副本,或者包含#include的无限循环。
#2
4
The problem is that you shouldn't be #include
ing a .c file.
问题是您不应该包含.c文件。
To use a function in another file, you need to declare it. Usually, every .c file (except main.c) has an associated header (.h) file that properly declares all the functions defined in the .c file. You can declare as many times as you want (so long as all the declarations are identical), but there can only be one definition.
要在另一个文件中使用函数,需要声明它。通常,每个.c文件(main.c除外)都有一个关联的头文件(.h),它正确地声明.c文件中定义的所有函数。您可以声明任意次数(只要所有的声明都是相同的),但是只能有一个定义。
What happens when you #include "add.c"
is that the text of add.c is included in main.c, giving main.c a definition (and, as a side-effect, a declaration) of add
. Then, when you compile add.c on it's own, that creates another definition of add
. Thus, there are two definitons of the function, and the compiler freaks out because it doesn't know which one to use.
当您#include“addc”时,会发生的事情是addc的文本包含在main中。c,给主。c是add的一个定义(还有一个副作用,一个声明),然后,当你自己编译addc时,就会创建add的另一个定义。
If you change it to #include "add.h"
, where add.h looks something like this:
如果你将它改为#include "add.h",其中add.h看起来是这样的:
#ifndef ADD_H
#define ADD_H
extern int add(int x, int y);
#endif /* ADD_H - Google "include guard" for more info about this trickery */
then main.c has a declaration of add
and can use the function, but the definition of add
is quite firmly only in the add.c file, and so it only exists once, and so it will compile properly.
那么主要。c有一个add的声明,并且可以使用这个函数,但是add的定义仅仅是在addc文件中,所以它只存在一次,所以它会正确地编译。
#3
2
Here is a simple example of calling a function from different c program
下面是一个调用来自不同c程序的函数的简单示例
let me name the main program as main.c and the program that holds the function as function.c for the function.c I am creating the header file called function.h
我把主程序命名为main。c和将函数保存为函数的程序。c函数。我正在创建名为function.h的头文件。
main.c
c
#include"function.h"
int main()
{
int a = sum(1,2);
return a;
}
function.c
function.c
int function(int a,int b)
{
return a+b;
}
function.h
function.h
int function(int,int);
To compile use the command given below
要编译,请使用下面给出的命令
g++ main.c function.c -o main
g++主要。c函数。c - o主要
Here the detailed explanation. In the main program I have called the function to sum 2 numbers. The values 1 and 2 in the main program was feed to the function in the function.c through the header function.h which holds the access point or the bridge to the function.c
这里的详细解释。在主程序中,我调用函数求和两个数。主程序中的值1和2被提供给函数中的函数。c通过header函数。h,它保存了访问点或功能的桥
For more details you can check the links given below
有关更多细节,请查看下面给出的链接
http://www.cplusplus.com/forum/beginner/34691/
http://www.cplusplus.com/forum/beginner/34691/
https://social.msdn.microsoft.com/Forums/en-US/4ea70f43-a0d5-43f8-8e24-78e90f208110/calling-a-function-in-a-file-from-another-file?forum=winembplatdev
https://social.msdn.microsoft.com/forums/en us/4ea70f43 - a0d5 - 43 - f8 - 8 e24 - 78 e90f208110/calling - a -功能- - -文件从file?forum=winembplatdev——另一个
Add a print statement to check the result or use echo $? after execution of the file main
添加一个打印语句来检查结果或使用echo $?执行后的文件主
#4
1
You're able to call it because a declaration isn't necessary to make a call in C. The return type however is unknown, and so will default to int
. This is possible in part due to the default calling convention in C, and the default promotion of types to at least int
precision.
你可以叫它因为声明没有必要打电话但是在C .返回类型是未知的,所以将默认为int。这可能部分由于默认的调用协定在C语言中,至少和默认推广类型int精度。
If you include a header that defines the function you are calling, the compiler is able to check that calls to the function have the correct number and type of arguments.
如果包含一个定义要调用的函数的头,编译器可以检查对函数的调用是否有正确的参数数量和类型。
If you include function definitions, they will be exported unless you specify their storage with static
. Since you're also compiling and linking add.c
, you can't add this since then either neither or both of your object files will then be exporting add
.
如果包含函数定义,那么它们将被导出,除非您使用静态方法指定它们的存储。由于您也在编译和链接addc,所以您不能添加这个,因为那时您的两个对象文件都不会导出添加。
If you want to simply include all your functions, best to put their definitions into headers, and sprinkle storage specifiers on them.
如果您只想包含所有的函数,那么最好将它们的定义放在header中,并在它们上面撒上存储说明符。