c语言编译器有哪些 gcc,C开发中的基本工具(GCC编译器)

这篇博客介绍了如何使用GCC编译C和C++程序,包括添加编译选项和链接库。对于C++,特别提到了需要链接`-lstdc++`来包含C++标准库。对于Fortran,讲解了gfortran前端的使用,并指出链接Fortran库的注意事项。同时,文章强调了在不同GCC版本中,Fortran前端的变化,如g77和gfortran的区别。
摘要由CSDN通过智能技术生成

rm -f hello hello.o hello_fn.o

该文件可以这样来读:使用 C 语言编译器

gcc,和编译选项‘-Wall’,从对象文件‘hello.o’和‘hello_fn.o’生成目标可执行文件

hello(文件‘hello.o’和‘hello_fn.o’通过隐含规则分别由‘hello.c’和‘hello_fn.c’生成)。目标clean

没有依赖文件,它只是简单地移除所有编译生成的文件。rm命令的选项 ‘-f’(force) 抑制文件不存在时产生的错误消息。

要使用该 makefile 文件,输入

make。不加参数调用make时,makefile文件中的第一个目标被建立,从而生成可执行文件‘hello’:

$ make

gcc -Wall -c -o hello.o hello.c

gcc -Wall -c -o hello_fn.o hello_fn.c

gcc hello.o hello_fn.o -o hello

$ ./hello

Hello, world!

一个源文件被修改要重新生成可执行文件,简单地再次输入 make 即可。通过检查目标文件和依赖文件的时间戳,程序 make

可识别哪些文件已经修改并依据对应的规则更新其对应的目标文件:

$ vim hello.c (打开编辑器修改一下文件)

$ make

gcc -Wall -c -o hello.o hello.c

gcc hello.o hello_fn.o -o hello

$ ./hello

Hello, world!

最后,我们移除 make 生成的文件,输入 make clean:

$ make clean

rm -f hello hello.o hello_fn.o

一个专业的 makefile文件通常包含用于安装(make install)和测试(make

check)等额外的目标。

本文中涉及到的例子都足够简单以至于可以完全不需要makefile,但是对任何大些的程序都使用 make 是很有必要的。

链接外部库

库是预编译的目标文件(object files)的集合,它们可被链接进程序。静态库以后缀为‘.a’的特殊的存档文件(archive

file)存储。

标准系统库可在目录 /usr/lib 与 /lib 中找到。比如,在类 Unix 系统中 C 语言的数学库一般存储为文件

/usr/lib/libm.a。该库中函数的原型声明在头文件 /usr/include/math.h 中。C 标准库本身存储为

/usr/lib/libc.a,它包含 ANSI/ISO C 标准指定的函数,比如‘printf’。对每一个 C

程序来说,libc.a 都默认被链接。

下面的是一个调用数学库 libm.a 中 sin 函数的的例子,创建文件calc.c:

#include

#include

int

main (void)

{

double x = sin (2.0);

printf ("The value of sin(2.0) is %f\n", x);

return 0;

}

尝试单独从该文件生成一个可执行文件将导致一个链接阶段的错误:

$ gcc -Wall calc.c -o calc

/tmp/ccbR6Ojm.o: In function 'main':

/tmp/ccbR6Ojm.o(.text+0x19): undefined reference to ‘sin’

函数 sin,未在本程序中定义也不在默认库‘libc.a’中;除非被指定,编译器也不会链接‘libm.a’。

为使编译器能将 sin

链接进主程序‘calc.c’,我们需要提供数学库‘libm.a’。一个容易想到但比较麻烦的做法是在命令行中显式地指定它:

$ gcc -Wall calc.c /usr/lib/libm.a -o calc

函数库‘libm.a’包含所有数学函数的目标文件,比如sin,cos,exp,log及sqrt。链接器将搜索所有文件来找到包含

sin 的目标文件。

一旦包含 sin 的目标文件被找到,主程序就能被链接,一个完整的可执行文件就可生成了:

$ ./calc

The value of sin(2.0) is 0.909297

可执行文件包含主程序的机器码以及函数库‘libm.a’中 sin 对应的机器码。

为避免在命令行中指定长长的路径,编译器为链接函数库提供了快捷的选项‘-l’。例如,下面的命令

$ gcc -Wall calc.c -lm -o calc

与我们上面指定库全路径‘/usr/lib/libm.a’的命令等价。

一般来说,选项 -lNAME使链接器尝试链接系统库目录中的函数库文件 libNAME.a。一个大型的程序通常要使用很多 -l

选项来指定要链接的数学库,图形库,网络库等。

编译C++与Fortran

GCC 是 GNU 编译器集合(GNU Compiler Collection)的首字母缩写词。GNU 编译器集合包含

C,C++,Objective-C,Fortran,Java 和 Ada

的前端以及这些语言对应的库(libstdc++,libgcj,……)。

前面我们只涉及到 C 语言,那么如何用 gcc 编译其他语言呢?本节将简单介绍 C++ 和 Fortran

编译的例子。

首先我们尝试编译简单的 C++ 的经典程序 Hello world:

#include

int main(int argc,char *argv[])

{

std::cout << "hello,

world\n";

return 0;

}

将文件保存为‘hello.cpp’,用 gcc 编译,结果如下:

$ gcc -Wall hello.cpp -o hello

/tmp/cch6oUy9.o: In function

`__static_initialization_and_destruction_0(int, int)':

hello.cpp:(.text+0x23): undefined reference to

`std::ios_base::Init::Init()'

/tmp/cch6oUy9.o: In function `__tcf_0':

hello.cpp:(.text+0x6c): undefined reference to

`std::ios_base::Init::~Init()'

/tmp/cch6oUy9.o: In function `main':

hello.cpp:(.text+0x8e): undefined reference to `std::cout'

hello.cpp:(.text+0x93): undefined reference to

`std::basic_ostream

std::char_traits

>&

std::operator<<

>(std::basic_ostream

std::char_traits

>&, char const*)'

/tmp/cch6oUy9.o:(.eh_frame+0x11): undefined reference to

`__gxx_personality_v0'

collect2: ld returned 1 exit status

出错了!!而且错误还很多,很难看懂,这可怎么办呢?在解释之前,我们先试试下面的命令:

$ gcc -Wall hello.cpp -o hello -lstdc++

噫,加上-lstdc++选项后,编译竟然通过了,而且没有任何警告。运行程序,结果如下:

$ ./hello

hello, world

通过上节,我们可以知道,-lstdc++ 选项用来通知链接器链接静态库

libstdc++.a。而从字面上可以看出,libstdc++.a 是C++ 的标准库,这样一来,上面的问题我们就不难理解了──编译

C++ 程序,需要链接 C++ 的函数库 libstdc++.a。

编译 C 的时候我们不需要指定 C 的函数库,为什么 C++ 要指定呢?这是由于早期 gcc 是指 GNU 的 C

语言编译器(GNU C Compiler),随着 C++,Fortran 等语言的加入,gcc的含义才变化成了 GNU

编译器集合(GNU Compiler Collection)。C作为 gcc 的原生语言,故编译时不需额外的选项。

不过幸运的是,GCC 包含专门为 C++ 、Fortran

等语言的编译器前端。于是,上面的例子,我们可以直接用如下命令编译:

$ g++ -Wall hello.cpp -o hello

GCC 的 C++ 前端是 g++,而 Fortran 的情况则有点复杂:在 gcc-4.0 版本之前,Fortran 前端是

g77,而gcc-4.0之后的版本对应的 Fortran 前端则改为 gfortran。下面我们先写一个简单的 Fortran

示例程序:

C Fortran 示例程序

PROGRAM HELLOWORLD

WRITE(*,10)

10 FORMAT('hello, world')

END PROGRAM HELLOWORLD

将文件保存‘hello.f’,用 GCC 的 Fortran 前端编译运行该文件

$ gfortran -Wall hello.f -o hello

$ ./hello

hello, world

我们已经知道,直接用 gcc 来编译 C++ 时,需要链接 C++ 标准库,那么用 gcc 编译

Fortran时,命令该怎么写呢?

$ gcc -Wall hello.f -o helloworld -lgfortran

-lgfortranbegin

注意:上面这条命令与 gfortran 前端是等价的(g77 与此稍有不同)。其中库文件 libgfortranbegin.a

(通过命令行选项 -lgfortranbegin 被调用) 包含运行和终止一个 Fortran 程序所必须的开始和退出代码。库文件

libgfortran.a 包含 Fortran 底层的输入输出等所需要的运行函数。

对于 g77 来说,下面两条命令是等价的(注意到 g77 对应的 gcc 是 4.0 之前的版本):

$ g77 -Wall hello.f -o hello

$ gcc-3.4 -Wall hello.f -o hello -lfrtbegin -lg2c

命令行中的两个库文件分别包含 Fortran 的开始和退出代码以及 Fortran 底层的运行函数。

gcc

也被称为高层次的简称

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值