Chinaunix
标题:
一个司空见惯的问题却突然想不通了:.h和.c文件有何关联?
[打印本页]
作者:
superwujc
时间:
2013-12-17 11:29
标题:
一个司空见惯的问题却突然想不通了:.h和.c文件有何关联?
问题描述:主程序文件a.c用于实现主要功能;自定义头文件b.h包含a.c所需的头文件的集合,以及自定义函数的原型声明;程序文件c.c包含自定义函数的定义(具体实现);三个文件位于同一目录下
如:
主程序a.c
#include <stdio.h>
#include "b.h"
int main (void)
{
int a, b;
a = 8;
b = 9;
function_a();
return 0;
}
复制代码
头文件b.h
void function_a(int, int);
复制代码
自定义函数的实现c.c
void function_a(int x, int y)
{
printf ("%d\n", x + y);
}
复制代码
请教各位,编译器会根据b.h自动加载c.c吗,还是必须显式手动指定c.c作为命令行参数?三者之间有无必然联系?如果有,是什么关系?
例子很简单,小弟当然可以自己实验看到结果,但烦请各位给出一个理论支撑,多谢。
作者:
linux_c_py_php
时间:
2013-12-17 11:47
#include是宏,把.h文件里的代码粘贴进来而已。
作者:
superwujc
时间:
2013-12-17 11:49
回复
2#
linux_c_py_php
但是如果.h里面只是函数的原型,但函数的实现是在另一个文件中定义的呢?
作者:
superwujc
时间:
2013-12-17 11:54
自己的实例验证:
主程序文件a.c
#include "b.h"
int main (void)
{
int a = 8;
int b = 9;
sum (a, b);
return 0;
}
复制代码
头文件b.h
#include <stdio.h>
void sum (int, int);
复制代码
自定义函数的实现c.c
#include "b.h"
void hello (void);
void sum (int x, int y)
{
printf ("sum is %d\n", x + y);
hello ();
}
void hello (void)
{
printf ("Hello!\n");
}
复制代码
编译并执行:
root@c-dev:/test# gcc a.c -o a
/tmp/ccLBu8OH.o: In function `main':
a.c:(.text+0x21): undefined reference to `sum'
collect2: ld returned 1 exit status
root@c-dev:/test# gcc a.c c.c -o a
root@c-dev:/test# a
sum is 17
Hello!
复制代码
结果如此,在编译时需要将自定义函数的实现文件指定为命令行参数
作者:
hejianet
时间:
2013-12-17 12:25
推荐楼主看一下linker&loader或者《程序员的自我修养》。
作者:
superwujc
时间:
2013-12-17 12:59
回复
5#
hejianet
多谢,会的
作者:
sqfasd
时间:
2013-12-17 13:39
本帖最后由 sqfasd 于 2013-12-17 13:54 编辑
superwujc 发表于 2013-12-17 12:59
回复 5# hejianet
多谢,会的
头文件主要就是把一系列的接口或变量放在一起打包声明,方便引用, 你可以不用头文件,每次都在c文件里使用之前声明一次也行, 但这样做不方便吗不是.
.h文件和.c文件没有必然的联系
头文件的声明是为了类型检查,在编译阶段起作用, 而定义是在链接的阶段起作用
还要注意c++和c的区别, c里面不必声明函数原型,就可以调用一个函数, 但c++为了安全起见必须要在编译阶段找到你调用的函数的原型的声明,否则编译不通过
作者:
sqfasd
时间:
2013-12-17 13:53
回复
4#
superwujc
如果你不把定义那个函数的源文件作为gcc的输入, 就不会去编译, 链接的时候也就找不到定义
你理所当然的认为编译器会去给你通过头文件推断出函数定义在哪, 事实上编译器不会去做推断, 也没必要
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2