69,373
社区成员
发帖
与我相关
我的任务
分享
/*
* main.c
*/
#include "binoheap.h" // 这样包含就连接错误,删了工程再建还是一样
#include "binoheap.c" // 这样就没问题,为什么?
/*
错误提示:
main.obj : error LNK2001: unresolved external symbol "struct tagBinoHeap __cdecl binomial_heap_insert(struct tagBinoHeap,struct tagBinoNode *)" (?binomial_heap_insert@@YA?AUtagBinoHeap@@U1@PAUtagBinoNode@@@Z)
main.obj : error LNK2001: unresolved external symbol "struct tagBinoHeap __cdecl make_binomial_heap(void)" (?make_binomial_heap@@YA?AUtagBinoHeap@@XZ)
Debug/binoheap.exe : fatal error LNK1120: 2 unresolved externals
*/
int main(void)
{
//...
}
/*
* binoheap.c
*/
#include "binoheap.h"
// 各种函数实现
/*
* binoheap.h
*/
#include <stdlib.h>
// include其他头文件
// 各种声明
/////////////////////////////////////////////////
// 然后我写了一个简单的int型加法函数测试了一下,包含.h和.c都是可以的,为什么。
extern int global_var;
void do_nothing();
2.源文件sc.cpp,这个文件定义全局变量和一个函数
#include "head1.h"
int global_var = 100;
void do_nothing(){
}
3.源文件main.cpp,这个文件使用了文件sc.cpp中定义的全局变量和函数
#include <iostream>
#include "head1.h"
using namespace std;
int main(){
do_nothing();
cout << global_var << endl;
return 0;
}
以上就是典型的外部引用函数和变量的方法。
另外补充几点:
1、编译的时候,编译器只会把各个源文件(*.c *.cpp)编译成二进制文件,然后链接成exe文件,这个你应该知道吧。就是说其实头文件(*.h)只是起到辅助作用。
2、#include这个预编译命令。其实很简单,在文件sc.cpp中#include "head1.h"就是在预编译的时候把head1.h中的所有代码照搬到sc.cpp中这个位置。#include另外一个源文件,这种做法或许可以让你的代码编译通过,但是极度不推荐。
3、更深层次一点东西:如何声明外部链接。
首先是函数,在一个源文件中,如果一个函数只有声明没有定义,编译器就认为这个函数引用自其他文件,比如上面那个例子中,main.cpp在include了head1.h之后,就有了函数do_nothing的声明,而没有定义。
而对于变量,变量的声明+定义其实是一起完成的,所以用extern关键字来修饰——在一个源文件中,如果某一个变量只有extern声明,编译器就认为这个变量来自其他文件。例如上面的例子,main.cpp在include了head1.h之后,就有了变量extern声明extern int global_var; 但是没有正常的int global_var;声明+定义,所以编译器知道这个变量来自其他文件。