gccg++编译命令选项
更新日期:
- 1. 1.预处理,生成.i的文件[预处理器cpp]
- 2. 2.将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs]
- 3. 3.有汇编变为目标代码(机器代码)生成.o的文件[汇编器as]
- 4. 4.连接目标代码,生成可执行程序[链接器ld]
g++是c++的命令,以.cpp为主,对于c语言后缀名一般为.c。这时候命令换做gcc即可。其实是无关紧要的。
其实编译器是根据gcc还是g++来确定是按照C标准还是C++标准编译链接。
下面以Test.cpp为例:
命令: g++ Test.cpp
功能:生成默认为a.exe的文件,这个过程包含了编译和链接。
再说下-o命令,-o命令表示输出的意思,gcc/g++命令是非常灵活的,你不指定输出的文件名的时候默认生成的是.exe文件。
你要输出Test.exe的话可以用:g++ -o Test.exe Test.cpp。-o命令是输出的意思,这样就输出了Test.exe。
gcc/g++在执行编译工作的时候,总共需要以下几步:
- /*
- Test.cpp
- */
- #include <IOSTREAM>
- static int t = 1;
- #define T 9
- using namespace std;
- typedef int Status;
- int main()
- {
- Status i = 1;
- cout << T i << endl; //Test Cout
- return 0;
- }
1.预处理,生成.i的文件[预处理器cpp]
命令:g++ -E Test.cpp > Test.i
功能:输出预处理后的文件,linux下以.i为后缀名。只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里 。这一步主要做了这些事情:宏的替换,还有注释的消除,还有找到相关的库文件。用编辑器打开Test.i会发现有很多很多代码,你只需要看最后部分就会发现,预处理做了宏的替换,还有注释的消除,可以理解为无关代码的清除。下面是Test.i文件的最后部分,可以看见宏的替换和注释的消除。
[cpp] view plaincopy
- # 5 "Test.cpp" 2
- static int t = 1;
- using namespace std;
- typedef int Status;
- int main()
- {
- Status i = 1;
- cout << 9 i << endl;
- return 0;
- }
2.将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs]
命令:g++ -S Test.cpp功能:会生成Test.s文件,.s文件表示是汇编文件,用编辑器打开就都是汇编指令。
3.有汇编变为目标代码(机器代码)生成.o的文件[汇编器as]
命令:g++ -c Test.cpp功能:.o是GCC生成的目标文件,除非你是做编译器和连接器调试开发的,否则打开这种.o没有任何意义。二进制机器码一般人也读不了。
4.连接目标代码,生成可执行程序[链接器ld]
命令:g++ Test.o -L F:\vs2008\VC\include\iostream功能:将.o文件与所需的库文件链接整合形成.exe文件,这就是可执行文件。-L 表示链接,这里我后面写的是绝对路径,相对各人电脑不同
在上面各个步骤中你可以用-o命令输出你自己想要的各种名字。比如最后一个命令,用下面的输出Test.exe
你可以g++ Test.o -o Test.exe -L F:\vs2008\VC\include\iostream
====================================================================================================
gcc and g++分别是gnu的c & c++编译器 gcc/g++在执行编译工作的时候,总共需要4步
1.预处理,生成.i的文件[预处理器cpp]
2.将预处理后的文件转换成汇编语言,生成文件.s[编译器egcs]
3.由汇编变为目标代码(机器代码)生成.o的文件[汇编器as]
4.连接目标代码,生成可执行程序[链接器ld]
[参数详解]
-x language filename
设定文件所使用的语言,使后缀名无效,对以后的多个有效.也就是根据约定C语言的后缀名称是.c的,而C++的后缀名是.C或者.cpp,如果你很个性,决定你的C代码文件的后缀名是.pig 哈哈,那你就要用这个参数,这个参数对他后面的文件名都起作用,除非到了下一个参数的使用。
可以使用的参数吗有下面的这些
c',objective-c’, c-header',c++’, cpp-output',assembler’, and `assembler-with-cpp’.
看到英文,应该可以理解的。
例子用法:
gcc -x c hello.pig
-x none filename
关掉上一个选项,也就是让gcc根据文件名后缀,自动识别文件类型
例子用法:
gcc -x c hello.pig -x none hello2.c
-c
只激活预处理,编译,和汇编,也就是他只把程序做成obj文件
例子用法:
gcc -c hello.c
他将生成.o的obj文件
-S
只激活预处理和编译,就是指把文件编译成为汇编代码。
例子用法
gcc -S hello.c
他将生成.s的汇编代码,你可以用文本编辑器察看
-E
只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面.
例子用法:
gcc -E hello.c > pianoapan.txt
gcc -E hello.c | more
慢慢看吧,一个hello word 也要与处理成800行的代码
-o
制定目标名称,缺省的时候,gcc 编译出来的文件是a.out,很难听,如果你和我有同感,改掉它,哈哈
例子用法
gcc -o hello.exe hello.c (哦,windows用习惯了)
gcc -o hello.asm -S hello.c
-pipe
使用管道代替编译中临时文件,在使用非gnu汇编工具的时候,可能有些问题
gcc -pipe -o hello.exe hello.c
-ansi
关闭gnu c中与ansi c不兼容的特性,激活ansi c的专有特性(包括禁止一些asm inline typeof关键字,以及UNIX,vax等预处理宏,
-fno-asm
此选项实现ansi选项的功能的一部分,它禁止将asm,inline和typeof用作关键字。
-fno-strict-prototype
只对g++起作用,使用这个选项,g++将对不带参数的函数,都认为是没有显式的对参数的个数和类型说明,而不是没有参数.
而gcc无论是否使用这个参数,都将对没有带参数的函数,认为城没有显式说明的类型
-fthis-is-varialble
就是向传统c++看齐,可以使用this当一般变量使用.
-fcond-mismatch
允许条件表达式的第二和第三参数类型不匹配,表达式的值将为void类型
-funsigned-char
-fno-signed-char
-fsigned-char
-fno-unsigned-char
这四个参数是对char类型进行设置,决定将char类型设置成unsigned char(前两个参数)或者 signed char(后两个参数)
-include file
包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设定,功能就相当于在代码中使用#include<filename>
例子用法:
gcc hello.c -include /root/pianopan.h
-imacros file
将file文件的宏,扩展到gcc/g++的输入文件,宏定义本身并不出现在输入文件中
-Dmacro
相当于C语言中的#define macro
-Dmacro=defn
相当于C语言中的#define macro=defn
-Umacro
相当于C语言中的#undef macro
-undef
取消对任何非标准宏的定义
-Idir
在你是用#include"file"的时候,gcc/g++会先在当前目录查找你所制定的头文件,如果没有找到,他回到缺省的头文件目录找,如果使用-I制定了目录,他
回先在你所制定的目录查找,然后再按常规的顺序去找.
对于#include<file>,gcc/g++会到-I制定的目录查找,查找不到,然后将到系统的缺省的头文件目录查找
-I-
就是取消前一个参数的功能,所以一般在-Idir之后使用
-idirafter dir
在-I的目录里面查找失败,讲到这个目录里面查找.
-iprefix prefix
-iwithprefix dir
一般一起使用,当-I的目录查找失败,会到prefix+dir下查找
-nostdinc
使编译器不再系统缺省的头文件目录里面找头文件,一般和-I联合使用,明确限定头文件的位置
-nostdin C++
规定不在g++指定的标准路经中搜索,但仍在其他路径中搜索,.此选项在创libg++库使用
-C
在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的
-M
生成文件关联的信息。包含目标文件所依赖的所有源代码你可以用gcc -M hello.c来测试一下,很简单。
-MM
和上面的那个一样,但是它将忽略由#include<file>造成的依赖关系。
-MD
和-M相同,但是输出将导入到.d的文件里面
-MMD
和-MM相同,但是输出将导入到.d的文件里面
-Wa,option
此选项传递option给汇编程序;如果option中间有逗号,就将option分成多个选项,然后传递给会汇编程序
-Wl.option
此选项传递option给连接程序;如果option中间有逗号,就将option分成多个选项,然后传递给会连接程序.
-llibrary
制定编译的时候使用的库
例子用法
gcc -lcurses hello.c
使用ncurses库编译程序
-Ldir
制定编译的时候,搜索库的路径。比如你自己的库,可以用它制定目录,不然
编译器将只在标准库的目录找。这个dir就是目录的名称。
-O0
-O1
-O2
-O3
编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-g
只是编译器,在编译的时候,产生调试信息。
-gstabs
此选项以stabs格式声称调试信息,但是不包括gdb调试信息.
-gstabs+
此选项以stabs格式声称调试信息,并且包含仅供gdb使用的额外调试信息.
-ggdb
此选项将尽可能的生成gdb的可以使用的调试信息.
-static
此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么
动态连接库,就可以运行.
-share
此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
-traditional
试图让编译器支持传统的C语言特性
[参考资料]
-Linux/UNIX高级编程
中科红旗软件技术有限公司编著.清华大学出版社出版
-Gcc man page
[ChangeLog]
-2002-08-10
ver 0.1 发布最初的文档
-2002-08-11
ver 0.11 修改文档格式
-2002-08-12
ver 0.12 加入了对静态库,动态库的参数
-2002-08-16
ver 0.16 增加了gcc编译的4个阶段的命令
运行 gcc/egcs
**运行 gcc/egcs***
GCC 是 GNU 的 C 和 C++ 编译器。实际上,GCC 能够编译三种语言:C、C++ 和 Object C(C 语言的一种面向对象扩展)。利用 gcc 命令可同时编译并连接 C 和 C++ 源程序。
如果你有两个或少数几个 C 源文件,也可以方便地利用 GCC 编译、连接并生成可执行文件。例如,假设你有两个源文件 main.c 和 factorial.c 两个源文件,现在要编译生成一个计算阶乘的程序。
代码:
———————–
清单 factorial.c
———————–
int factorial (int n)
{
if (n <= 1)
return 1;
else
return factorial (n - 1) n;
}
———————–
清单 main.c
———————–
#include <stdio.h>
#include <unistd.h>
int factorial (int n);
int main (int argc, char argv)
{
int n;
if (argc < 2)
{
printf ("Usage: %s n\n", argv [0]);
return -1;
}
else
{
n = atoi (argv[1]);
printf ("Factorial of %d is %d.\n", n, factorial (n));
}
return 0;
}
———————–
利用如下的命令可编译生成可执行文件,并执行程序:
$ gcc -o factorial main.c factorial.c
$ ./factorial 5
Factorial of 5 is 120.
GCC 可同时用来编译 C 程序和 C++ 程序。一般来说,C 编译器通过源文件的后缀名来判断是 C 程序还是 C++ 程序。在 Linux 中,C 源文件的后缀名为 .c,而 C++ 源文件的后缀名为 .C 或 .cpp。但是,gcc 命令只能编译 C++ 源文件,而不能自动和 C++ 程序使用的库连接。因此,通常使用 g++ 命令来完成 C++ 程序的编译和连接,该程序会自动调用 gcc 实现编译。假设我们有一个如下的 C++ 源文件(hello.C):
#include <iostream>
void main (void)
{
cout << "Hello, world!" << endl;
}
则可以如下调用 g++ 命令编译、连接并生成可执行文件:
$ g++ -o hello hello.C
$ ./hello
Hello, world!
**gcc/egcs 的主要选项**
gcc 命令的常用选项
选项 解释
-ansi 只支持 ANSI 标准的 C 语法。这一选项将禁止 GNU C 的某些特色,
例如 asm 或 typeof 关键词。
-c 只编译并生成目标文件。
-DMACRO 以字符串“1”定义 MACRO 宏。
-DMACRO=DEFN 以字符串“DEFN”定义 MACRO 宏。
-E 只运行 C 预编译器。
-g 生成调试信息。GNU 调试器可利用该信息。
-IDIRECTORY 指定额外的头文件搜索路径DIRECTORY。
-LDIRECTORY 指定额外的函数库搜索路径DIRECTORY。
-lLIBRARY 连接时搜索指定的函数库LIBRARY。
-m486 针对 486 进行代码优化。
-o FILE 生成指定的输出文件。用在生成可执行文件时。
-O0 不进行优化处理。
-O 或 -O1 优化生成代码。
-O2 进一步优化。
linux下c++编程环境搭建,运行过程以及调试
安装g++环境
安装两个RPM包即可搞定
1 2 | [root@localhost Desktop]# rpm -ivh /home/weiwei/Desktop/libstdc++-devel-4.4.5-6.el6.i686.rpm [root@localhost Desktop]# rpm -ivh /home/weiwei/Desktop/gcc-c++-4.4.5-6.el6.i686.rpm |
查看g++是否安装成功
1 2 3 4 5 6 | [root@localhost Desktop]# g++ -vUsing built-in specs.Target: i686-redhat-linuxConfigured with: ../configure –prefix=/usr –mandir=/usr/share/man –infodir=/usr/share/info –with-bugurl=http://bugzilla.redhat.com/bugzilla –enable-bootstrap –enable-shared –enable-threads=posix –enable-checking=release –with-system-zlib –enable-__cxa_atexit –disable-libunwind-exceptions –enable-gnu-unique-object –enable-languages=c,c++,objc,obj-c++,java,fortran,ada –enable-java-awt=gtk –disable-dssi –with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre –enable-libgcj-multifile –enable-java-maintainer-mode –with-ecj-jar=/usr/share/java/eclipse-ecj.jar –disable-libjava-multilib –with-ppl –with-cloog –with-tune=generic –with-arch=i686 –build=i686-redhat-linuxThread model: posixgcc version 4.4.5 20110214 (Red Hat 4.4.5-6) (GCC) |
gcc与g++的区别
gcc可以用来编译C或者C++,但他只能编译c++源文件,不能自动和C++程序使用的库连接,g++可以实现C++程序的编译和链接,其实他也是调用gcc来编译的,要编译c++代码生成可执行文件要用 g++
编写一个简单的c++程序
1 2 3 4 5 6 7 8 9 10 11 | // myfirst.cpp–displays a message#include <iostream> // make definitions visibleusing namespace std; int main() // function header{ // start of function body cout << "Come up and C++ me some time."; // message cout << endl; // start a new line cout << "You won’t regret it!" << endl; // more output return 10; // terminate main() 返回值为0代表成功,非0返回值的含义由系统自定义} // end of function body |
打开命令窗口进行编译
1 | [root@localhost Desktop]# g++ -o test1 test.cpp |
-o test1 test.cpp 从test.cpp编译生成test1文件,test1为可执行文件,没有后缀
如果不写-o test1 会默认生成一个a.out可执行文件
执行可执行文件
1 2 3 | [root@localhost Desktop]# ./a.outCome up and C++ me some time.You won’t regret it! |
获取main函数返回值
1 2 | [root@localhost Desktop]# echo $?10 |
c/c++运行流程分解
预处理阶段
对c源文件预处理生成中间文件e.i
1 | [root@localhost c]# g++ -E funcuse.c -o e.i |
编译阶段
对预处理文件进行处理生成汇编语言文件e.s
1 | [root@localhost c]# g++ -S e.i -o e.s |
上述两部可以直接合并为
1 | [root@localhost c]# g++ -s e.i -o e.s |
汇编阶段
生成目标文件,目标文件是机器代码,但不能执行,必须将目标文件与其他目标文件或库文件连接生成可执行的二进制文件才能执行
1 | [root@localhost c]# g++ -c e.s -o e.o |
生成执行文件
1 | [root@localhost c]# g++ e.o -o result |
运行result
1 | [root@localhost c]# ./result |
在linux操作系统中运行程序必须指定程序所在的目录,除非程序的目录已经列在PATH环境变量中,所以程序前必须加./
注:echo $? 显示main函数的返回值(int型)
如果想让编译和运行同时进行可以采用如下命令:
gcc funcuse.c -o result && ./result
&&表示如果成功就。。。如果编译成功,会直接运行程序
可以将上述所有步骤合并写为
1 | g++ funcuse.c -o result |
或
1 | g++ -o result funcuse.c |
直接生成可执行文件
头文件与源文件
程序如果复杂的话,程序的各个部分会分别存储在不同的文件中,按照逻辑进行划分。
来自:http://www.cnblogs.com/lidabo/archive/2012/04/17/2454568.html
头文件的作用就是被其他的.cpp包含,本身并不参与编译,但实际上它们的内容却在多个.cpp文件中得到了 编译.
头文件中应该只放变量和函数的声明,而不能放它们的定义
这个规则是有三个例外的
头文件中可以写const对象的定义
头文件中可 以写内联函数(inline)的定义
头文件中可以写类 (class)的定义
分离式编译
如果将程序分成若干子程序,怎样在linux下进行编译呢?
下面以求圆的面积为例来说明
Circle.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #ifndef CIRCLE_H#define CIRCLE_Hclass Circle{ private: double r; public: Circle(); Circle(double R); double Area();};#endif |
Circle.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include "Circle.h"#include <iostream>using namespace std;Circle::Circle(){ this->r=5.0;}Circle::Circle(double R){ this->r=R;}double Circle:: Area(){ return 3.14rr;} |
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 | #include "Circle.h"#include <iostream>using namespace std;int main(int argc, char argv[]){ Circle c(3); cout<<"Area="<<c.Area()<<endl; return 0;} |
编译
1 2 3 4 5 | [root@localhost cpp]# g++ -c Circle.cpp -o Circle.o[root@localhost cpp]# g++ -c main.cpp -o main.o[root@localhost cpp]# g++ main.o Circle.o -o main[root@localhost cpp]# ./mainArea=28.26 |
-c命令表示编译,头文件不许显式编译,但实际已经编译。如果只修改了一个源文件,只需要编译改动的文件
makefile
但如果我们的程序有几百个源程序的时候,怎么办?难道也要编译器重新一个一个的编译?
makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
1 2 3 4 5 6 7 | #此行为注释main: main.o Circle.o g++ main.o Circle.o -o mainCircle.o:Circle.cpp g++ -c Circle.cpp -o Circle.omain.o:main.cpp g++ -c main.cpp -o main.o |
注意:g++命令开头的行前面必须有tab空格,不然会报错: ** missing separator. Stop
如果将名字命名为Makefile或makefile,只需要在命令行下敲入make就可以进行自动化编译
1 2 3 4 5 6 | [root@localhost cpp]# makeg++ -c main.cpp -o main.og++ -c Circle.cpp -o Circle.og++ main.o Circle.o -o main[root@localhost cpp]# ./mainArea=28.26 |
参考:
http://blog.163.com/dong_box/blog/static/2625977820103310933870/
[精华] 跟我一起写 Makefile - ChinaUnix.net
编写Makefile - 学习,思考,记录,分享。 - 博客频道 - CSDN.NET
GDB调试
启动gdb
1 2 3 4 5 6 7 8 9 10 | [root@localhost c]# gdbGNU gdb (GDB) Red Hat Enterprise Linux (7.2-48.el6)Copyright (C) 2010 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "i686-redhat-linux-gnu".For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>. |
调试前要先进性编译连接
1 | [root@localhost c]# g++ -g funcuse.c -o dbug |
进行调试
1 2 | [root@localhost c]# gdb dbugReading symbols from /home/weiwei/Desktop/c/dbug…done. |
列出代码
1 2 3 4 5 6 7 8 9 | (gdb) list1 #include<stdio.h>2 3 int main(){4 for(int i=0 ; i<5; i++){5 printf("this is %d\n",i);6 }7 return 0;8 } |
1 2 3 4 | (gdb) list 3,53 int main(){4 for(int i=0 ; i<5; i++){5 printf("this is %d\n",i); |
执行程序
1 2 3 4 5 6 7 | (gdb) runStarting program: /home/weiwei/Desktop/c/dbug this is 0this is 1this is 2this is 3this is 4 |
设置断点
1 2 | (gdb) break 5Breakpoint 1 at 0x8048487: file funcuse.c, line 5. |
运行
1 2 3 4 5 6 | (gdb) rStarting program: /home/weiwei/Desktop/c/dbug Breakpoint 1, main () at funcuse.c:55 printf("this is %d\n",i);Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.25.el6.i686 libgcc-4.4.5-6.el6.i686 libstdc++-4.4.5-6.el6.i686 |
到断点处程序停止,继续运行输入continue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | (gdb) cContinuing.this is 0Breakpoint 1, main () at funcuse.c:55 printf("this is %d\n",i);(gdb) cContinuing.this is 1Breakpoint 1, main () at funcuse.c:55 printf("this is %d\n",i);(gdb) cContinuing.this is 2 |
监测某一个值
1 2 | (gdb) watch iHardware watchpoint 2: i |
1 2 3 4 5 6 7 8 9 | (gdb) cContinuing.this is 3Hardware watchpoint 2: iOld value = 3New value = 40x080484a0 in main () at funcuse.c:44 for(int i=0 ; i<5; i++){ |
查看某一个特定的变量
1 | (gdb) print i |
自动显示变量的值,每次运行到断点处都会自动显示
1 | (gdb) display i |
查看当前自动显示的所有变量
1 2 3 4 | (gdb) info displayAuto-display expressions now in effect:Num Enb Expression1: y i |
查看变量类型
1 2 | (gdb) whatis itype = int |
单步执行,step进入函数内部( 使用return命令跳出来 ,跳出前可以使用finish执行完函数体),next把函数当成一条语句不进入函数内部
1 2 | (gdb) step (gdb) next |
删除编号为1的断点
1 | (gdb) delete 1 |
</
