GNU CC(GNU Compiler Collection, GNU编译器套件,简称GCC), 是GNU开发的编程语言编译器。
GCC命令使用GNU推出的基于C/C++的编译器,是开放源代码领域应用最广泛的编译器,具有功能强大,编译代码支持性能优化等特点。现在很多程序员都应用GCC,怎样才能更好的应用GCC。目前,GCC可以用来编译C/C++、FORTRAN、JAVA、OBJC、ADA等语言的程序。
主要学习Linux下使用gcc编译C、C++程序。
先来了解C/C++编译原理:
源代码 -> 预处理 -> 编译 -> 链接 -> 可执行文件
预处理:将所有头文件(包括系统头文件*.h)和源代码(*.c)整理成一个文件(这个阶段只是简单检查存在这些文件而已,不检查语法)
编译:先将预处理出来的文件汇编成汇编语言文件(*.s),然后再将汇编后的文件(*.s)编译为目标文件(*.o)。当然这两个过程都会检查语法。
链接:将目标文件(*.o)和库文件链接生成可执行文件。
关于具体如何使用GCC,可以从这里学习,总结非常好,这位仁兄。 http://man.linuxde.net/gcc
1、GCC是非常严谨的。 相对来说,VS是很宽松的,是这个意思。
在VS上能通过的例子,GCC不一定能通过,
在GCC能通过的代码,VS一定能通过。
2、C/C++链接的库是完全不一样的,也就是说C和C++的库是放在不同位置的。尽管C++里面有很多实现是类似C(C++中的C那部分)。
3 C的目标代码不会改变函数名,而C++的目标代码会改变函数名(重载机制),并且相对应的库也不一样
(C和C++编译器编译完,它们的目标代码不一样)
nm命令:显示关于对象文件、可执行文件以及对象昂文件库里的符号信息
ldd命令: 命令用于判断某个可执行的binary档案含有什么动态库。
hello.c /hello.cpp 如下:
<span style="font-size:18px;">stu@ubuntu:~/test$ ls
hello.c
stu@ubuntu:~/test$ vi hello.c
#include<stdio.h>
#include<stdlib.h>
int add(int a,int b)
{
return a+b;
}
int main(int argc,char *argv[])
{
if(argc<3)
{
printf("输入参数太少\n");
}
else
{
int a=atoi(argv[1]);
int b=atoi(argv[2]);
printf("%d+%d=%d\n",a,b,a+b);
}
return 0;
} </span>
C语言编译
<span style="font-size:18px;">stu@ubuntu:~/test$ ls
hello.c
stu@ubuntu:~/test$ gcc -o hello hello.c //用C编译
stu@ubuntu:~/test$ ls
hello hello.c
stu@ubuntu:~/test$ nm hello
08049f28 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
0804858c R _IO_stdin_used
w _Jv_RegisterClasses
08049f18 d __CTOR_END__
08049f14 d __CTOR_LIST__
08049f20 D __DTOR_END__
08049f1c d __DTOR_LIST__
080486cc r __FRAME_END__
08049f24 d __JCR_END__
08049f24 d __JCR_LIST__
0804a01c A __bss_start
0804a014 D __data_start
08048540 t __do_global_ctors_aux
080483b0 t __do_global_dtors_aux
0804a018 D __dso_handle
w __gmon_start__
08048532 T __i686.get_pc_thunk.bx
08049f14 d __init_array_end
08049f14 d __init_array_start
08048530 T __libc_csu_fini
080484c0 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
0804a01c A _edata
0804a024 A _end
0804856c T _fini
08048588 R _fp_hw
080482f0 T _init
08048380 T _start
08048434 T add //add函数名没有变
U atoi@@GLIBC_2.0
0804a01c b completed.6159
0804a014 W data_start
0804a020 b dtor_idx.6161
08048410 t frame_dummy
08048441 T main //main函数
U printf@@GLIBC_2.0
U puts@@GLIBC_2.0</span>
C语言的库
<span style="font-size:18px;">stu@ubuntu:~/test$ ls
hello.c
stu@ubuntu:~/test$ gcc -o hello hello.c
stu@ubuntu:~/test$ ls
hello hello.c
stu@ubuntu:~/test$ ./hello 1 2
1+2=3
stu@ubuntu:~/test$ ldd hello
linux-gate.so.1 => (0xb775a000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75a2000)
/lib/ld-linux.so.2 (0xb775b000)
stu@ubuntu:~/test$ </span>
c++编译
<span style="font-size:18px;">stu@ubuntu:~/test$ ls
hello.c
stu@ubuntu:~/test$ mv hello.c hello.cpp
stu@ubuntu:~/test$ gcc -o hello hello.cpp -lstdc++ //C++编译.cpp
stu@ubuntu:~/test$ ls
hello hello.cpp
stu@ubuntu:~/test$ nm hello
08049f28 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
0804858c R _IO_stdin_used
w _Jv_RegisterClasses
08048434 T _Z3addii //add函数名已经改变 这也说明了C++的重载机制, 目标带代码的函数名跟原来函数名不一致
08049f18 d __CTOR_END__
08049f14 d __CTOR_LIST__
08049f20 D __DTOR_END__
08049f1c d __DTOR_LIST__
080486cc r __FRAME_END__
08049f24 d __JCR_END__
08049f24 d __JCR_LIST__
0804a01c A __bss_start
0804a014 D __data_start
08048540 t __do_global_ctors_aux
080483b0 t __do_global_dtors_aux
0804a018 D __dso_handle
w __gmon_start__
08048532 T __i686.get_pc_thunk.bx
08049f14 d __init_array_end
08049f14 d __init_array_start
08048530 T __libc_csu_fini
080484c0 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
0804a01c A _edata
0804a024 A _end
0804856c T _fini
08048588 R _fp_hw
080482f0 T _init
08048380 T _start
U atoi@@GLIBC_2.0
0804a01c b completed.6159
0804a014 W data_start
0804a020 b dtor_idx.6161
08048410 t frame_dummy
08048441 T main
U printf@@GLIBC_2.0
U puts@@GLIBC_2.0</span>
C++相关的库<span style="font-size:18px;">stu@ubuntu:~/test$ ldd hello
linux-gate.so.1 => (0xb7797000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75df000)
/lib/ld-linux.so.2 (0xb7798000)</span>