GCC学习资料

上一篇 / 下一篇  2008-12-19 11:23:05 / 个人分类:linux

51Testing软件测试网 jVh|j uJ,?

学习GCC的时候,在网上搜集的部分入门的资料.希望对您有所帮助!
r$k*{ lQ5G.Ii051Testing软件测试网]j4rP0]}@Xj
一、GCC简介51Testing软件测试网fS/M$x] t7a f

.gEQ im0通常所说的GCC是GUN Compiler Collection的简称,除了编译程序之外,它还含其他相关工具,所以它能把易于人类使用的高级语言编写的源代码构建成计算机能够直接执行的二进制代码。GCC是Linux平台下最常用的编译程序,它是Linux平台编译器的事实标准。同时,在Linux平台下的嵌入式开发领域,GCC也是用得最普遍的一种编译器。GCC之所以被广泛采用,是因为它能支持各种不同的目标体系结构。例如,它既支持基于宿主的开发(简单讲就是要为某平台编译程序,就在该平台上编译),也支持交叉编译(即在A平台上编译的程序是供平台B使用的)。目前,GCC支持的体系结构有四十余种,常见的有X86系列、Arm、PowerPC等。同时,GCC还能运行在不同的操作系统上,如Linux、Solaris、Windows等。
\jc-s2ON'k0
Qe dC| f5b051Testing软件测试网.|3\d$v1\wu4v
除了上面讲的之外,GCC除了支持C语言外,还支持多种其他语言,例如C++、Ada、Java、Objective-C、FORTRAN、Pascal等。
},npc|d(K051Testing软件测试网 n2N WB]%Q
51Testing软件测试网#[d,E b$fq~
本系列文章中,我们不仅介绍GCC的基本功能,还涉及到一些诸如优化之类的高级功能。另外,我们还考察GCC的一些映像操作工具,如size和objcopy等,这将在后续的文章中加以介绍。
a _.k7L rf1F051Testing软件测试网KRY'MFn;yh4J
51Testing软件测试网x"G)M o:aP8A/?,zH
二、程序的编译过程
]H dZR_W!Y051Testing软件测试网 ^#N^'me(i u(]
51Testing软件测试网4Nf5I G5y h.e
对于GUN编译器来说,程序的编译要经历预处理、编译、汇编、连接四个阶段,如下图所示:51Testing软件测试网r-b+B~A-^Jp

:a%V;K9{,IW1k!YtB051Testing软件测试网P&q)kTQ-v

"HV(i$h R8j)?xtko0
#C:u5d`K&[?c051Testing软件测试网d5d%wg`*_S]
从功能上分,预处理、编译、汇编是三个不同的阶段,但GCC的实际操作上,它可以把这三个步骤合并为一个步骤来执行。下面我们以C语言为例来谈一下不同阶段的输入和输出情况。
)@^SU [%bwYE0
N1m!M?q+Rt051Testing软件测试网z J A#Zy-g
在预处理阶段,输入的是C语言的源文件,通常为*.c。它们通常带有.h之类头文件的包含文件。这个阶段主要处理源文件中的#ifdef、 #include和#define命令。该阶段会生成一个中间文件*.i,但实际工作中通常不用专门生成这种文件,因为基本上用不到;若非要生成这种文件不可,可以利用下面的示例命令:51Testing软件测试网C+OC%q0AV"~]&Z
51Testing软件测试网n(N{A;C&S f(|

-eF |_T&hD3M5M051Testing软件测试网&cTM5Ei1g
51Testing软件测试网&A uq*{;z}w#X.L{
gcc -E test.c -o test.i
Fola9u [R7Zf051Testing软件测试网7l aa'}| tg5d
51Testing软件测试网];}%At@v q g8H
51Testing软件测试网/Flw,k:J#l2zX
51Testing软件测试网/M$E7p$fPh0r
在编译阶段,输入的是中间文件*.i,编译后生成汇编语言文件*.s 。这个阶段对应的GCC命令如下所示:51Testing软件测试网;X:_.h@ r I
51Testing软件测试网5d2OM)J(~\

R!O-WU.pW2s0
(ZD3T7P4[2S051Testing软件测试网/p:S)R z2T&i1P
GCC -S test.i -o test.s51Testing软件测试网QN0`]6T| m c\tk
51Testing软件测试网 Yw:oY6lX
51Testing软件测试网8R m1z w3i S*jc;k

M+U[Ame0
^-iw!z%x*I6lW:g0在汇编阶段,将输入的汇编文件*.s转换成机器语言*.o。这个阶段对应的GCC命令如下所示:51Testing软件测试网2I!T,i"LK

\"j&jW[S051Testing软件测试网)^O&^2s;lTmG

S4v'A:pu.r0K@#kT051Testing软件测试网v Y8Y/r$W
GCC -c test.s -o test.o51Testing软件测试网n2Y+T jdQb[
51Testing软件测试网t6f'c qF:GZ
51Testing软件测试网$@KD r'pmg}
51Testing软件测试网4}9o0{+W3bN{
51Testing软件测试网RWCH,l q
最后,在连接阶段将输入的机器代码文件*.s(与其它的机器代码文件和库文件)汇集成一个可执行的二进制代码文件。这一步骤,可以利用下面的示例命令完成:51Testing软件测试网%U_7r/U3a[)_
51Testing软件测试网{4A*y(U/i;t H
51Testing软件测试网/Zh['gZdY

K"` rBK8pz;^0
)A?1b+K4j,X(R]L$_0GCC test.o -o test51Testing软件测试网7An8b/M7@"iW@

nWsx9C2L;B051Testing软件测试网6kzSOE9j2Ks.Zi1}$~Y
51Testing软件测试网;@[{Yk|W%t
51Testing软件测试网:y] {;J{}$IO!l
上面介绍了GCC编译过程的四个阶段以及相应的命令。下面我们进一步介绍常用的GCC的模式。
M2Y*xE*NpeN t |$`Q)M0
:m6t'AO7{q[2I]0
:OrC7s h { i0三、GCC常用模式51Testing软件测试网J+FmxC ~5p(o*n#b
51Testing软件测试网\!P?D7s\wh.lQv

:JZ;_&FqT[7m#V*E0这里介绍GCC追常用的两种模式:编译模式和编译连接模式。下面以一个例子来说明各种模式的使用方法。为简单起见,假设我们全部的源代码都在一个文件test.c中,要想把这个源文件直接编译成可执行程序,可以使用以下命令:51Testing软件测试网m`;W.d x3UZ_&X!B

0Sz4ANDw8RH)^0
F_ kn/C0
"Nf,NXF(jG051Testing软件测试网 z"Z!lT%l9V1?q!a3N Tg8_
$ GCC -o test
l$u,Jpyi l0
#fvr$@P1[ W0
,k n'rK0p,{:|!V051Testing软件测试网S h}oz8A1_J
51Testing软件测试网y"W h,s4n%n!Q#] MR+q1^
这里test.c是源文件,生成的可执行代码存放在一个名为test 的文件中(该文件是机器代码并且可执行)。-o 是生成可执行文件的输出选项。如果我们只想让源文件生成目标文件(给文件虽然也是机器代码但不可执行),可以使用标记-c ,详细命令如下所示:51Testing软件测试网!U$Uho.^ gpsYx'e
51Testing软件测试网']$RZ;o!{ q%E"~Y&H ]
51Testing软件测试网9`;^\Q]Mc2B
51Testing软件测试网Bnt}3it
51Testing软件测试网Q:WV]/|6U
$ GCC -c test.c51Testing软件测试网"I/_qRSl

*L;F+p;I&m'c6]051Testing软件测试网om1f?{Q ~a
51Testing软件测试网9dWX.yJ ^Q;u
51Testing软件测试网7D#x`Z%~`
默认情况下,生成的目标文件被命名为test.o,但我们也可以为输出文件指定名称,如下所示:
,uJ"G,`ggl{051Testing软件测试网@ J%P0C}*V1@!s1k1_e e
51Testing软件测试网,?6v}^y/WT:yX
51Testing软件测试网d!w_|S VGH

9NH \ g"_%{p V7^0$ GCC -c test.c -o
,n~#Ck u0
F#x^[NZ-r0~051Testing软件测试网+\}Uud|&s

/t~[ B}2|051Testing软件测试网 Tf,D5T9VK
上面这条命令将编译后的目标文件命名为mytest.o,而不是默认的test.o。51Testing软件测试网SW jC9h(V"U
51Testing软件测试网6\:FxOm }dN
51Testing软件测试网 jb#R H ^|
迄今为止,我们谈论的程序仅涉及到一个源文件;现实中,一个程序的源代码通常包含在多个源文件之中,这该怎么办?没关系,即使这样,用GCC处理起来也并不复杂,见下例:51Testing软件测试网Th Ly }

;I;M*rIs}"Y051Testing软件测试网F/u&e~@JXm

,S.fg Z2yX0
YR`E~8v3\3Wu0$ GCC -o test first.c second.c third.c51Testing软件测试网 gc,p+h0O-E
51Testing软件测试网f"vdr7IH

:Q6O1~C$M1H*X1i051Testing软件测试网Du DZ-R7W\c
51Testing软件测试网L"\K)bI G&H&O I`-N
需要注意的是,要生成可执行程序时,一个程序无论有有一个源文件还是多个源文件,所有被编译和连接的源文件中必须有且仅有一个main函数,因为main函数是该程序的入口点(换句话说,当系统调用该程序时,首先将控制权授予程序的main函数)。但如果仅仅是把源文件编译成目标文件的时候,因为不会进行连接,所以main函数不是必需的。
4v:uq#[)R051Testing软件测试网A,K f a"B

K'M8Z.t'k ~1I0四、常用选项
d7M/y TQ }}`l051Testing软件测试网 {]wEq$E9s0{ Ju
51Testing软件测试网9NDd#H't:C^9W
许多情况下,头文件和源文件会单独存放在不同的目录中。例如,假设存放源文件的子目录名为./src,而包含文件则放在层次的其他目录下,如./inc。当我们在./src 目录下进行编译工作时,如何告诉GCC到哪里找头文件呢?方法如下所示:51Testing软件测试网8ftXWQ f

8^z d+c Ntu051Testing软件测试网s7W&Zwvjo
51Testing软件测试网 X7~hf;m0@'y
51Testing软件测试网!g9H*sY hr
$ gcc test.c �I../inc -o test51Testing软件测试网!s2vJ"m\Z-B
51Testing软件测试网5BS _Zsdd@J
51Testing软件测试网P,K,RG]a|7}8A

w6xR[:H0
T#F7fxg+Cx+d v+O2U3yb0上面的命令告诉GCC包含文件存放在./inc 目录下,在当前目录的上一级。如果在编译时需要的包含文件存放在多个目录下,可以使用多个-I 来指定各个目录:51Testing软件测试网6r,P/|.Z/W pXY
51Testing软件测试网#ME({V*q9Z xr zJ(rAa.|

.WVFi5pWnG051Testing软件测试网$KR"[:p8M[0E(X

!~ik3`BL c0$ gcc test.c �I../inc �I../../inc2 -o test51Testing软件测试网O!T BQ$w~

.X'l&@7M1h"|,y_051Testing软件测试网-c c4xM U,Q/}

&T(dRe!v_051Testing软件测试网-AG UP5M,j8S
这里指出了另一个包含子目录inc2,较之前目录它还要在再上两级才能找到。
;e,L(P;z't;Z051Testing软件测试网2a+\&^5^'A6VO
51Testing软件测试网 |4]+rZzA
另外,我们还可以在编译命令行中定义符号常量。为此,我们可以简单的在命令行中使用-D选项即可,如下例所示:
y e1k0@2i'f h0
Q;\9HQh){Gp051Testing软件测试网+^5k&V5Z*}%u
51Testing软件测试网r(i,N A6x0m!_
51Testing软件测试网9NJ"G:k5R
$ gcc -DTEST_CONFIGURATION test.c -o test51Testing软件测试网+vgTllS%S[

`+l8@;` hhh0
s,PGg+j`x0
+^i@I.J&{G:_f0
!IYE4?8SV0上面的命令与在源文件中加入下列命令是等效的:51Testing软件测试网 j G\ W\*XG+bG ] p

`7D!m {:f8HO,z051Testing软件测试网5_:LvC2IQ

A&wa&O5s0W2r0
){5[t6z Br|,X!Q:I0#define TEST_CONFIGURATION51Testing软件测试网s u5Wl~t?k+wp

ee9qU%K*`)_ F{'F0
Zx VL)aV051Testing软件测试网u&f4hk3p@3dw[8`
51Testing软件测试网(luR*pqF"HV.a
在编译命令行中定义符号常量的好处是,不必修改源文件就能改变由符号常量控制的行为。
q,f;y c$sK`E^0
G/lQ(h@j051Testing软件测试网BjWX N0QX
五、警告功能
cF.bt4h0
!ZU3n!fd8c051Testing软件测试网'j6ym'O'K
当GCC在编译过程中检查出错误的话,它就会中止编译;但检测到警告时却能继续编译生成可执行程序,因为警告只是针对程序结构的诊断信息,它不能说明程序一定有错误,而是存在风险,或者可能存在错误。虽然GCC提供了非常丰富的警告,但前提是你已经启用了它们,否则它不会报告这些检测到的警告。
/]u5G-M9Fo;yW0
#@4K!N E3rZ051Testing软件测试网!b yj^FJ-e]\"~ I6w
在众多的警告选项之中,最常用的就是-Wall选项。该选项能发现程序中一系列的常见错误警告,该选项用法举例如下:51Testing软件测试网 n&|7X7^h o`o X['h

*to[s1M0
i6vxZ N#JO051Testing软件测试网4J/^;Heoz)x4HF'o

sqF9^ R"s0$ gcc -Wall test.c -o test
x9iX,j3A e'N0
0fY*Zg~1D051Testing软件测试网c]?8tW
51Testing软件测试网5j2F(@$z&p
51Testing软件测试网O#~ vJ!K"z tt'Q#a
该选项相当于同时使用了下列所有的选项:
wB&}W {$K0
TNO'Ao051Testing软件测试网(p$Y pzr.q#N&iD%@7\f%hK
◆unused-function:遇到仅声明过但尚未定义的静态函数时发出警告。
1lp)kGBn|051Testing软件测试网5Dn'PGsH
◆unused-label:遇到声明过但不使用的标号的警告。
7v(S1xZ7?&NrlC051Testing软件测试网I4d k{~c]
◆unused-parameter:从未用过的函数参数的警告。51Testing软件测试网J:G3}U~NR

F,T6[@^8Q.d:S0◆unused-variable:在本地声明但从未用过的变量的警告。51Testing软件测试网N\w%e@p_5g

:oyu T#o#P0◆unused-value:仅计算但从未用过的值得警告。51Testing软件测试网G`VBT2d
51Testing软件测试网9WxU~?_ ^
◆Format:检查对printf和scanf等函数的调用,确认各个参数类型和格式串中的一致。
*Gs}IdZ051Testing软件测试网,a4IN;e0VT
◆implicit-int:警告没有规定类型的声明。
)KVfB3Q1t"k3V0
PPbu5zygs0◆implicit-function-:在函数在未经声明就使用时给予警告。51Testing软件测试网$N#rx3|c0zc`r7]

"R*w"H*r tr%g0◆char-subscrīpts:警告把char类型作为数组下标。这是常见错误,程序员经常忘记在某些机器上char有符号。51Testing软件测试网1d]!|,}9j&D@

t%K a1]w%Rg!t0◆missing-braces:聚合初始化两边缺少大括号。51Testing软件测试网~YyXc6a$_
51Testing软件测试网uFK)S6i8b5p2o6x
◆Parentheses:在某些情况下如果忽略了括号,编译器就发出警告。
^^bXV(N(`051Testing软件测试网*mV#KIf*@J#F
◆return-type:如果函数定义了返回类型,而默认类型是int型,编译器就发出警告。同时警告那些不带返回值的 return语句,如果他们所属的函数并非void类型。51Testing软件测试网u"|Hc4p.jP
51Testing软件测试网i,c{uO.Gj9Y |1Z4q
◆sequence-point:出现可疑的代码元素时,发出报警。
C+J3w4YZ8P4Um051Testing软件测试网 E U!T kf$|m$S
◆Switch:如果某条switch语句的参数属于枚举类型,但是没有对应的case语句使用枚举元素,编译器就发出警告(在switch语句中使用default分支能够防止这个警告)。超出枚举范围的case语句同样会导致这个警告。51Testing软件测试网TkzoA}!g'S7N T W

W@ tB mk8I0◆strict-aliasing:对变量别名进行最严格的检查。51Testing软件测试网kj+Q mQ$M^

as;]2V;{:P~{u0◆unknown-pragmas:使用了不允许的#pragma。51Testing软件测试网 n6R5bQ ^3xm v[5r,a

~,x'VF,Ga]0◆Uninitialized:在初始化之前就使用自动变量。51Testing软件测试网V J:uT0c[L&r1|
51Testing软件测试网)GC(`.U"c1g
51Testing软件测试网$c8A4B(A t6g:K
需要注意的是,各警告选项既然能使之生效,当然也能使之关闭。比如假设我们想要使用-Wall来启用个选项,同时又要关闭unused警告,利益通过下面的命令来达到目的:51Testing软件测试网1k*l:\;?F U4} sO
51Testing软件测试网k:o3v3x2Nu
51Testing软件测试网1q2o[(?Dta)mT&?
51Testing软件测试网0[;Tr/u7^
51Testing软件测试网#V!P7x h!Z+jq"g
$ gcc -Wall -Wno-unused test.c -o test
;su}xkCA051Testing软件测试网+va r$xU
51Testing软件测试网S9~:P&n;i ~0mH)i
51Testing软件测试网1z#u'Rm8i,X3T4?|
51Testing软件测试网 P-jp L1o
下面是使用-Wall选项的时候没有生效的一些警告项:51Testing软件测试网}1C(G0k$si

*o/svd2I.o7g051Testing软件测试网*B2T&cIuI$AT ]}
◆cast-align:一旦某个指针类型强制转换时,会导致目标所需的地址对齐边界扩展,编译器就发出警告。例如,某些机器上只能在2或4字节边界上访问整数,如果在这种机型上把char *强制转换成int *类型, 编译器就发出警告。51Testing软件测试网H-WV1D] m&M7|

6a jd&X+z,T)?F0◆sign-compare:将有符号类型和无符号类型数据进行比较时发出警告。51Testing软件测试网:@]PK fI+w(d

o7v:?#qA0◆missing-prototypes :如果没有预先声明函数原形就定义了全局函数,编译器就发出警告。即使函数定义自身提供了函数原形也会产生这个警告。这样做的目的是检查没有在头文件中声明的全局函数。
2]2n Y"fr|051Testing软件测试网Zg P-sq tH
◆Packed:当结构体带有packed属性但实际并没有出现紧缩式给出警告。51Testing软件测试网;j Z$l"ico
51Testing软件测试网"|.|mI6X Q
◆Padded:如果结构体通过充填进行对齐则给出警告。
*w0y} _g]&@ o051Testing软件测试网#j&D5m-SI+T~"yO
◆unreachable-code:如果发现从未执行的代码时给出警告。51Testing软件测试网6l/erj1Q3c3}i
51Testing软件测试网gSw%}|)i#y\
◆Inline:如果某函数不能内嵌(inline),无论是声明为inline或者是指定了-finline-functions 选项,编译器都将发出警告。
5]7c4u1V$i%`-jne$` ] n051Testing软件测试网 W/Y#G/W-hT_x'n#|
◆disabled-optimization:当需要太长时间或过多资源而导致不能完成某项优化时给出警告。
'G_EHAlf5ur0
FU7n:X iw051Testing软件测试网,z3lUE/~A7N$~
上面是使用-Wall选项时没有生效,但又比较常用的一些警告选项。本文中要介绍的最后一个常用警告选项是-Werror。使用该选项后,GCC发现可疑之处时不会简单的发出警告就算完事,而是将警告作为一个错误而中断编译过程。该选项在希望得到高质量代码时非常有用。51Testing软件测试网fB,`:x(S2dv"nl L

N T(b5nC6`^0
GKS*\EJz0六、小结51Testing软件测试网#p~7Z"g!?qg

7`O A T0aT K0
Pdr k\/Qo?x:u~0本文介绍了GCC的基本编译过程和编译模式,并详细阐述了GCC的一些常用选项以及警告功能。这些是在利用GCC进行应用编程时最基本也最常用的一些内容,我们会在后续文章中继续介绍GCC的调试和优化技术

^N1e%U2^!i.bnf051Testing软件测试网n"\Q'hs!\e kLM

转自:http://www.linuxsir.com/bbs/thread283910.html

-z)\ ^3@8dp0

TAG: linux

 

评分:0

我来说两句

Open Toolbar