Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
标准库与c中的用户定义头文件(.h)及其实现文件(.c)有何不同?_C_Static Libraries_Header Files - Fatal编程技术网

标准库与c中的用户定义头文件(.h)及其实现文件(.c)有何不同?

标准库与c中的用户定义头文件(.h)及其实现文件(.c)有何不同?,c,static-libraries,header-files,C,Static Libraries,Header Files,在main.c中使用#include包含的libc.a(静态库)等标准库与main.c中包含的用户定义头文件(cube.h)及其在c中的实现文件(cube.c)有何不同 我的意思是两者都是头文件,但一个实现是静态库(.a),另一个实现是源文件(.c) 您可以在cube.c中定义(实现) #include "cube.h" int cube( int x ) { return x * x * x; } 然后我们将把函数声明放在另一个文件中。按照惯例,在本例中,这是在头文件cube.h中完

在main.c中使用
#include
包含的libc.a(静态库)等标准库与main.c中包含的用户定义头文件(cube.h)及其在c中的实现文件(cube.c)有何不同

我的意思是两者都是头文件,但一个实现是静态库(.a),另一个实现是源文件(.c)

您可以在cube.c中定义(实现)

#include "cube.h"

int cube( int x ) {
   return x * x * x;
}
然后我们将把函数声明放在另一个文件中。按照惯例,在本例中,这是在头文件cube.h中完成的

int cube( int x );
现在,我们可以使用#include指令(c预处理器的一部分)从其他地方调用函数,例如main.c

#包括“cube.h”
#包括
int main(){
int c=立方体(10);
printf(“%d”,c);
...
}

另外,如果我在cube.h中包含了include-guards,那么当我在main.c和cube.c中都包含cube.h时会发生什么。它将包括在哪里

编程语言与其实现不同

编程语言是一种规范(写在纸上;您应该阅读,它实际上是C11标准),而不是软件。C标准指定了一个C标准库,并将标题定义为
#include
-d

(你可以在没有任何计算机的情况下,用一堆人类奴隶运行你的C程序;这是非常不道德的;你也可以使用类似于解释器的解释器,避免使用任何编译器、对象或可执行文件)

libc.a
(静态库)这样的标准库如何使用
#include
。。。不同于用户文件
cube.c

上面的句子完全错误(毫无意义)
libc.a
#包括
头(即文件
/usr/include/stdio.h
和其他内部头,例如
/usr/include/bits/stdio2.h
)。当编译
main.c
cube.c
时,就会出现这种包含

原则上,
可能不是计算机上的任何文件(例如,
#include
可能会在编译器中触发一些魔法)。实际上,当您
#include
时,编译器正在解析
/usr/include/stdio.h
(以及其他包含的文件)

一些标准头(特别是
,…)是由标准指定的,但在编译器的特殊或(即“神奇”东西)帮助下实现

C标准知道

编译器处理(大体上说,实现翻译单元)并从一个阶段(处理和其他指令以及扩展宏)开始。而
gcc
不仅运行编译器本身(一些
cc1
),而且还运行汇编程序
as
ld
(更多信息,请阅读Levine的书)

出于充分的理由,您的头文件
cube.h
实际上应该以开头。在你过于简单的例子中,它们可能是无用的(但你应该养成这个习惯)

您几乎应该始终使用
gcc-Wall-Wextra-g
(以获取所有警告和调试信息)。阅读这一章

您还可以将
-v
传递给
gcc
,以了解实际运行的程序(例如
cc1
ld
as

您可以将
-H
传递到
gcc
,以了解在预处理阶段包含哪些源文件。您还可以通过
gcc-c-eccube.c>cube.i
获得
cube.c
的预处理形式的
cube.c
作为
cube.i
文件,然后使用一些编辑器或寻呼机查看该
cube.i
文件

您(或
gcc
)需要(在您的示例中)将
cube.c
(该文件及其包含的每个头文件给出的翻译单位)编译到
cube.o
(假设是Linux系统)中。您还可以将
main.c
编译成
main.o
。最后,
gcc
将链接
cube.o
main.o
、一些启动文件(阅读相关内容)和
libc.so
共享库(实现POSIX C标准库规范等)以生成。对象文件、共享(和静态库,如果您使用一些)和可执行文件在Linux上使用文件格式

如果你用几个源文件(和翻译单元)编写一个C程序,你实际上应该使用类似的工具

如果我在cube.h中包含了include-guards,那么当我在main.c和cube.c中都包含cube.h时会发生什么

这应该是两个不同的翻译单元。您可以分几个步骤来编译它们。首先,使用以下命令将
main.c
编译为
main.o

 gcc -Wall -Wextra -g -c main.c
gcc -Wall -Wextra -g -c cube.c
上面的命令正在生成一个
main.o
对象文件(借助于
cc1
as

然后使用以下命令编译(另一个翻译单元)
cube.c

 gcc -Wall -Wextra -g -c main.c
gcc -Wall -Wextra -g -c cube.c
因此获得
cube.o

(请注意,在
cube.h
中添加include-guard不会改变这样一个事实:它将被读取两次,一次是在编译
cube.c
时,另一次是在编译
main.c
时)

最后,使用

gcc -Wall -Wextra -g cube.o main.o -o yourprog
(我邀请您尝试所有这些命令,并使用
gcc-v
而不是上面的
gcc
来尝试它们)

请注意,
gcc-Wall-Wextra-gcube.cmain.c-oyourprog
正在运行上述所有步骤(使用
gcc-v
检查)。您确实应该编写一个脚本来避免键入所有这些命令(只需使用
make
进行编译,或者更好地使用
make-j
并行运行编译)

最后,您可以使用
/y运行可执行文件
% gcc foo.c -Wall -Werror
% ./a.out 
2.000000
%
% cat foo.c 
#include <math.h>
#include <stdio.h>

int main(void) {
    double n;
    scanf("%lf\n", &n);
    printf("%f\n", sqrt(n));
}
% gcc foo.c -Wall -Werror
/tmp/ccTipZ5Q.o: In function `main':
foo.c:(.text+0x3d): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
% cat foo.c
int printf(const char * restrict format, ...);
double sqrt(double x);

int main(void) {
    printf("%f\n", sqrt(4.0));
}
% gcc foo.c -std=c11 -pedantic -Wall -Werror
% ./a.out
2.000000
int printf(const char * restrict format, ...);

int main(void) {
    printf("%f\n", sqrt(4));
}
% gcc foo.c -std=c11 -pedantic
foo.c: In function ‘main’:
foo.c:4:20: warning: implicit declaration of function ‘sqrt’
             [-Wimplicit-function-declaration]
     printf("%f\n", sqrt(4));
                    ^~~~
foo.c:4:20: warning: incompatible implicit declaration of built-in function ‘sqrt’
foo.c:4:20: note: include ‘<math.h>’ or provide a declaration of ‘sqrt’
% ./a.out
2.000000