GCC编译器入门

时间:2021-04-17 09:10:30

  GCC(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的编程语言编译器。它是以GPL许可证所发行的*软件,也是 GNU计划的关键部分。GCC原本作为GNU操作系统的官方编译器,现已被大多数类Unix操作系统(如Linux、BSD、Mac OS X等)采纳为标准的编译器,GCC同样适用于微软的Windows。 GCC是*软件过程发展中的著名例子,由*软件基金会以GPL协议发布。它处理能够高效的编译C语言以外,还可以编译其他语言。并且,现在的GCC已经不光包括编译器本身,还包含了编译过程中的工具链。

 

1 GCC编译流程

在学习使用GCC编译程序之前,首先要知道编译C程序的基本流程,一般情况下分为下面四步:

(1) 对C语言进行预处理,生成*.i文件。

(2) 将上一步生成的*.i文件编译生成汇编语言文件,后缀名为*.s

(3) 将汇编语言文件*.s经过汇编,生成目标文件,后缀名为*.o

(4) 将各个模块的*.o文件链接起来,生成最终的可执行文件

 

2 GCC常用选项

GCC的编译选项非常多,现在有上千个,但是我们常用的并不多,下面我们只介绍其中非常实用的几个。

在这之前,我们先编写下面的几个源文件,以备测试只用。

 

GCC编译器入门GCC编译器入门
 1 //main.c
2 #include <stdio.h>
3
4 extern int add(int a, int b);
5 extern int mul(int a, int b);
6
7 int main(void)
8 {
9 int a = 10, b = 5;
10 int result;
11
12 result = add(a, mul(a, b));
13 printf("result = %d\n", result);
14 return 0;
15 }
main.c
GCC编译器入门GCC编译器入门
1 //test1.c
2 int add(int a, int b)
3 {
4 return a+b;
5 }
test1.c
GCC编译器入门GCC编译器入门
1 //test2.c
2 int mul(int a, int b)
3 {
4 return a*b;
5 }
test2.c

 

2.1 -c选项

  该选项(小写c)表示编译、汇编指定的源文件,但是不进行链接。该选项的使用方法如下:

gcc -c source.c

也就是在-c选项后面紧跟要编译、汇编的C源文件,最终生成与源文件名称相同,但是后缀为*.o结尾的目标文件。

xiaomanon@xiaomanon-machine:~/Documents/c_code$ ls
main.c test1.c test2.c
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ gcc -c test1.c
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ls
main.c test1.c test1.o test2.c

可以看到,使用-c选项编译之后生成了对应的*.o目标文件。当然,你也可以一次性指定多个C源文件,使用-c选项后,会针对每一个C源文件生成一个相应的*.o目标文件。

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -c test2.c main.c
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ls
main.c main.o test1.c test1.o test2.c test2.o

 

2.2 -S选项

  该选项(大写S)将C语言源文件编译生成汇编语言文件,但是并不汇编该程序。注意:汇编过程的作用是将汇编语言文件编译成目标文件*.o,而-S选项的作用是得到汇编语言文件*.s。该选项的使用方法为:

gcc -S source.c

使用该选项,最终生成与源文件名称相同,但是后缀为*.s结尾的汇编语言文件。

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -S test1.c
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ls
main.c test1.c test1.s test2.c

当然,输入的源文件也不止一个,你可以编译当前目录下的所有C语言源文件:

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -S *.c
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ls
main.c main.s test1.c test1.s test2.c test2.s

我们也可以查看生成的汇编语言代码:

GCC编译器入门GCC编译器入门
 1     .file    "test1.c"
2 .text
3 .globl add
4 .type add, @function
5 add:
6 .LFB0:
7 .cfi_startproc
8 pushl %ebp
9 .cfi_def_cfa_offset 8
10 .cfi_offset 5, -8
11 movl %esp, %ebp
12 .cfi_def_cfa_register 5
13 movl 12(%ebp), %eax
14 movl 8(%ebp), %edx
15 addl %edx, %eax
16 popl %ebp
17 .cfi_restore 5
18 .cfi_def_cfa 4, 4
19 ret
20 .cfi_endproc
21 .LFE0:
22 .size add, .-add
23 .ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
24 .section .note.GNU-stack,"",@progbits
test1.s

 

2.3 -E选项

  该选项对C语言源文件进行预处理,但是并不编译该程序。对于一般的预处理问题(比如,宏的展开问题、文件的包含问题等),可以使用这个选项进行查看。另外,如果直接使用此选项,程序会将预处理结果直接输出到终端,不便于查看,因此,一般可以使用重定向将程序输出结果保存到一个文本文件中,格式如下:

gcc -E source.c > output

如果我们对main.c执行预编译,得到的output文件内容如下:

GCC编译器入门GCC编译器入门
  1 # 1 "main.c"
2 # 1 "<command-line>"
3 # 1 "/usr/include/stdc-predef.h" 1 3 4
4 # 1 "<command-line>" 2
5 # 1 "main.c"
6
7 # 1 "/usr/include/stdio.h" 1 3 4
8 # 27 "/usr/include/stdio.h" 3 4
9 # 1 "/usr/include/features.h" 1 3 4
10 # 374 "/usr/include/features.h" 3 4
11 # 1 "/usr/include/i386-linux-gnu/sys/cdefs.h" 1 3 4
12 # 385 "/usr/include/i386-linux-gnu/sys/cdefs.h" 3 4
13 # 1 "/usr/include/i386-linux-gnu/bits/wordsize.h" 1 3 4
14 # 386 "/usr/include/i386-linux-gnu/sys/cdefs.h" 2 3 4
15 # 375 "/usr/include/features.h" 2 3 4
16 # 398 "/usr/include/features.h" 3 4
17 # 1 "/usr/include/i386-linux-gnu/gnu/stubs.h" 1 3 4
18
19
20
21
22
23
24 # 1 "/usr/include/i386-linux-gnu/gnu/stubs-32.h" 1 3 4
25 # 8 "/usr/include/i386-linux-gnu/gnu/stubs.h" 2 3 4
26 # 399 "/usr/include/features.h" 2 3 4
27 # 28 "/usr/include/stdio.h" 2 3 4
28
29
30
31
32
33 # 1 "/usr/lib/gcc/i686-linux-gnu/4.8/include/stddef.h" 1 3 4
34 # 212 "/usr/lib/gcc/i686-linux-gnu/4.8/include/stddef.h" 3 4
35 typedef unsigned int size_t;
36 # 34 "/usr/include/stdio.h" 2 3 4
37
38 # 1 "/usr/include/i386-linux-gnu/bits/types.h" 1 3 4
39 # 27 "/usr/include/i386-linux-gnu/bits/types.h" 3 4
40 # 1 "/usr/include/i386-linux-gnu/bits/wordsize.h" 1 3 4
41 # 28 "/usr/include/i386-linux-gnu/bits/types.h" 2 3 4
42
43
44 typedef unsigned char __u_char;
45 typedef unsigned short int __u_short;
46 typedef unsigned int __u_int;
47 typedef unsigned long int __u_long;
48
49
50 typedef signed char __int8_t;
51 typedef unsigned char __uint8_t;
52 typedef signed short int __int16_t;
53 typedef unsigned short int __uint16_t;
54 typedef signed int __int32_t;
55 typedef unsigned int __uint32_t;
56
57
58
59
60 __extension__ typedef signed long long int __int64_t;
61 __extension__ typedef unsigned long long int __uint64_t;
62
63
64
65
66
67
68
69 __extension__ typedef long long int __quad_t;
70 __extension__ typedef unsigned long long int __u_quad_t;
71 # 121 "/usr/include/i386-linux-gnu/bits/types.h" 3 4
72 # 1 "/usr/include/i386-linux-gnu/bits/typesizes.h" 1 3 4
73 # 122 "/usr/include/i386-linux-gnu/bits/types.h" 2 3 4
74
75
76 __extension__ typedef __u_quad_t __dev_t;
77 __extension__ typedef unsigned int __uid_t;
78 __extension__ typedef unsigned int __gid_t;
79 __extension__ typedef unsigned long int __ino_t;
80 __extension__ typedef __u_quad_t __ino64_t;
81 __extension__ typedef unsigned int __mode_t;
82 __extension__ typedef unsigned int __nlink_t;
83 __extension__ typedef long int __off_t;
84 __extension__ typedef __quad_t __off64_t;
85 __extension__ typedef int __pid_t;
86 __extension__ typedef struct { int __val[2]; } __fsid_t;
87 __extension__ typedef long int __clock_t;
88 __extension__ typedef unsigned long int __rlim_t;
89 __extension__ typedef __u_quad_t __rlim64_t;
90 __extension__ typedef unsigned int __id_t;
91 __extension__ typedef long int __time_t;
92 __extension__ typedef unsigned int __useconds_t;
93 __extension__ typedef long int __suseconds_t;
94
95 __extension__ typedef int __daddr_t;
96 __extension__ typedef int __key_t;
97
98
99 __extension__ typedef int __clockid_t;
100
101
102 __extension__ typedef void * __timer_t;
103
104
105 __extension__ typedef long int __blksize_t;
106
107
108
109
110 __extension__ typedef long int __blkcnt_t;
111 __extension__ typedef __quad_t __blkcnt64_t;
112
113
114 __extension__ typedef unsigned long int __fsblkcnt_t;
115 __extension__ typedef __u_quad_t __fsblkcnt64_t;
116
117
118 __extension__ typedef unsigned long int __fsfilcnt_t;
119 __extension__ typedef __u_quad_t __fsfilcnt64_t;
120
121
122 __extension__ typedef int __fsword_t;
123
124 __extension__ typedef int __ssize_t;
125
126
127 __extension__ typedef long int __syscall_slong_t;
128
129 __extension__ typedef unsigned long int __syscall_ulong_t;
130
131
132
133 typedef __off64_t __loff_t;
134 typedef __quad_t *__qaddr_t;
135 typedef char *__caddr_t;
136
137
138 __extension__ typedef int __intptr_t;
139
140
141 __extension__ typedef unsigned int __socklen_t;
142 # 36 "/usr/include/stdio.h" 2 3 4
143 # 44 "/usr/include/stdio.h" 3 4
144 struct _IO_FILE;
145
146
147
148 typedef struct _IO_FILE FILE;
149
150
151
152
153
154 # 64 "/usr/include/stdio.h" 3 4
155 typedef struct _IO_FILE __FILE;
156 # 74 "/usr/include/stdio.h" 3 4
157 # 1 "/usr/include/libio.h" 1 3 4
158 # 31 "/usr/include/libio.h" 3 4
159 # 1 "/usr/include/_G_config.h" 1 3 4
160 # 15 "/usr/include/_G_config.h" 3 4
161 # 1 "/usr/lib/gcc/i686-linux-gnu/4.8/include/stddef.h" 1 3 4
162 # 16 "/usr/include/_G_config.h" 2 3 4
163
164
165
166
167 # 1 "/usr/include/wchar.h" 1 3 4
168 # 82 "/usr/include/wchar.h" 3 4
169 typedef struct
170 {
171 int __count;
172 union
173 {
174
175 unsigned int __wch;
176
177
178
179 char __wchb[4];
180 } __value;
181 } __mbstate_t;
182 # 21 "/usr/include/_G_config.h" 2 3 4
183 typedef struct
184 {
185 __off_t __pos;
186 __mbstate_t __state;
187 } _G_fpos_t;
188 typedef struct
189 {
190 __off64_t __pos;
191 __mbstate_t __state;
192 } _G_fpos64_t;
193 # 32 "/usr/include/libio.h" 2 3 4
194 # 49 "/usr/include/libio.h" 3 4
195 # 1 "/usr/lib/gcc/i686-linux-gnu/4.8/include/stdarg.h" 1 3 4
196 # 40 "/usr/lib/gcc/i686-linux-gnu/4.8/include/stdarg.h" 3 4
197 typedef __builtin_va_list __gnuc_va_list;
198 # 50 "/usr/include/libio.h" 2 3 4
199 # 144 "/usr/include/libio.h" 3 4
200 struct _IO_jump_t; struct _IO_FILE;
201 # 154 "/usr/include/libio.h" 3 4
202 typedef void _IO_lock_t;
203
204
205
206
207
208 struct _IO_marker {
209 struct _IO_marker *_next;
210 struct _IO_FILE *_sbuf;
211
212
213
214 int _pos;
215 # 177 "/usr/include/libio.h" 3 4
216 };
217
218
219 enum __codecvt_result
220 {
221 __codecvt_ok,
222 __codecvt_partial,
223 __codecvt_error,
224 __codecvt_noconv
225 };
226 # 245 "/usr/include/libio.h" 3 4
227 struct _IO_FILE {
228 int _flags;
229
230
231
232
233 char* _IO_read_ptr;
234 char* _IO_read_end;
235 char* _IO_read_base;
236 char* _IO_write_base;
237 char* _IO_write_ptr;
238 char* _IO_write_end;
239 char* _IO_buf_base;
240 char* _IO_buf_end;
241
242 char *_IO_save_base;
243 char *_IO_backup_base;
244 char *_IO_save_end;
245
246 struct _IO_marker *_markers;
247
248 struct _IO_FILE *_chain;
249
250 int _fileno;
251
252
253
254 int _flags2;
255
256 __off_t _old_offset;
257
258
259
260 unsigned short _cur_column;
261 signed char _vtable_offset;
262 char _shortbuf[1];
263
264
265
266 _IO_lock_t *_lock;
267 # 293 "/usr/include/libio.h" 3 4
268 __off64_t _offset;
269 # 302 "/usr/include/libio.h" 3 4
270 void *__pad1;
271 void *__pad2;
272 void *__pad3;
273 void *__pad4;
274 size_t __pad5;
275
276 int _mode;
277
278 char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
279
280 };
281
282
283 typedef struct _IO_FILE _IO_FILE;
284
285
286 struct _IO_FILE_plus;
287
288 extern struct _IO_FILE_plus _IO_2_1_stdin_;
289 extern struct _IO_FILE_plus _IO_2_1_stdout_;
290 extern struct _IO_FILE_plus _IO_2_1_stderr_;
291 # 338 "/usr/include/libio.h" 3 4
292 typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes);
293
294
295
296
297
298
299
300 typedef __ssize_t __io_write_fn (void *__cookie, const char *__buf,
301 size_t __n);
302
303
304
305
306
307
308
309 typedef int __io_seek_fn (void *__cookie, __off64_t *__pos, int __w);
310
311
312 typedef int __io_close_fn (void *__cookie);
313 # 390 "/usr/include/libio.h" 3 4
314 extern int __underflow (_IO_FILE *);
315 extern int __uflow (_IO_FILE *);
316 extern int __overflow (_IO_FILE *, int);
317 # 434 "/usr/include/libio.h" 3 4
318 extern int _IO_getc (_IO_FILE *__fp);
319 extern int _IO_putc (int __c, _IO_FILE *__fp);
320 extern int _IO_feof (_IO_FILE *__fp) __attribute__ ((__nothrow__ , __leaf__));
321 extern int _IO_ferror (_IO_FILE *__fp) __attribute__ ((__nothrow__ , __leaf__));
322
323 extern int _IO_peekc_locked (_IO_FILE *__fp);
324
325
326
327
328
329 extern void _IO_flockfile (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__));
330 extern void _IO_funlockfile (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__));
331 extern int _IO_ftrylockfile (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__));
332 # 464 "/usr/include/libio.h" 3 4
333 extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict,
334 __gnuc_va_list, int *__restrict);
335 extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict,
336 __gnuc_va_list);
337 extern __ssize_t _IO_padn (_IO_FILE *, int, __ssize_t);
338 extern size_t _IO_sgetn (_IO_FILE *, void *, size_t);
339
340 extern __off64_t _IO_seekoff (_IO_FILE *, __off64_t, int, int);
341 extern __off64_t _IO_seekpos (_IO_FILE *, __off64_t, int);
342
343 extern void _IO_free_backup_area (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__));
344 # 75 "/usr/include/stdio.h" 2 3 4
345
346
347
348
349 typedef __gnuc_va_list va_list;
350 # 90 "/usr/include/stdio.h" 3 4
351 typedef __off_t off_t;
352 # 102 "/usr/include/stdio.h" 3 4
353 typedef __ssize_t ssize_t;
354
355
356
357
358
359
360
361 typedef _G_fpos_t fpos_t;
362
363
364
365
366 # 164 "/usr/include/stdio.h" 3 4
367 # 1 "/usr/include/i386-linux-gnu/bits/stdio_lim.h" 1 3 4
368 # 165 "/usr/include/stdio.h" 2 3 4
369
370
371
372 extern struct _IO_FILE *stdin;
373 extern struct _IO_FILE *stdout;
374 extern struct _IO_FILE *stderr;
375
376
377
378
379
380
381
382 extern int remove (const char *__filename) __attribute__ ((__nothrow__ , __leaf__));
383
384 extern int rename (const char *__old, const char *__new) __attribute__ ((__nothrow__ , __leaf__));
385
386
387
388
389 extern int renameat (int __oldfd, const char *__old, int __newfd,
390 const char *__new) __attribute__ ((__nothrow__ , __leaf__));
391
392
393
394
395
396
397
398
399 extern FILE *tmpfile (void) ;
400 # 209 "/usr/include/stdio.h" 3 4
401 extern char *tmpnam (char *__s) __attribute__ ((__nothrow__ , __leaf__)) ;
402
403
404
405
406
407 extern char *tmpnam_r (char *__s) __attribute__ ((__nothrow__ , __leaf__)) ;
408 # 227 "/usr/include/stdio.h" 3 4
409 extern char *tempnam (const char *__dir, const char *__pfx)
410 __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;
411
412
413
414
415
416
417
418
419 extern int fclose (FILE *__stream);
420
421
422
423
424 extern int fflush (FILE *__stream);
425
426 # 252 "/usr/include/stdio.h" 3 4
427 extern int fflush_unlocked (FILE *__stream);
428 # 266 "/usr/include/stdio.h" 3 4
429
430
431
432
433
434
435 extern FILE *fopen (const char *__restrict __filename,
436 const char *__restrict __modes) ;
437
438
439
440
441 extern FILE *freopen (const char *__restrict __filename,
442 const char *__restrict __modes,
443 FILE *__restrict __stream) ;
444 # 295 "/usr/include/stdio.h" 3 4
445
446 # 306 "/usr/include/stdio.h" 3 4
447 extern FILE *fdopen (int __fd, const char *__modes) __attribute__ ((__nothrow__ , __leaf__)) ;
448 # 319 "/usr/include/stdio.h" 3 4
449 extern FILE *fmemopen (void *__s, size_t __len, const char *__modes)
450 __attribute__ ((__nothrow__ , __leaf__)) ;
451
452
453
454
455 extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __attribute__ ((__nothrow__ , __leaf__)) ;
456
457
458
459
460
461
462 extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __attribute__ ((__nothrow__ , __leaf__));
463
464
465
466 extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf,
467 int __modes, size_t __n) __attribute__ ((__nothrow__ , __leaf__));
468
469
470
471
472
473 extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,
474 size_t __size) __attribute__ ((__nothrow__ , __leaf__));
475
476
477 extern void setlinebuf (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
478
479
480
481
482
483
484
485
486 extern int fprintf (FILE *__restrict __stream,
487 const char *__restrict __format, ...);
488
489
490
491
492 extern int printf (const char *__restrict __format, ...);
493
494 extern int sprintf (char *__restrict __s,
495 const char *__restrict __format, ...) __attribute__ ((__nothrow__));
496
497
498
499
500
501 extern int vfprintf (FILE *__restrict __s, const char *__restrict __format,
502 __gnuc_va_list __arg);
503
504
505
506
507 extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg);
508
509 extern int vsprintf (char *__restrict __s, const char *__restrict __format,
510 __gnuc_va_list __arg) __attribute__ ((__nothrow__));
511
512
513
514
515
516 extern int snprintf (char *__restrict __s, size_t __maxlen,
517 const char *__restrict __format, ...)
518 __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 4)));
519
520 extern int vsnprintf (char *__restrict __s, size_t __maxlen,
521 const char *__restrict __format, __gnuc_va_list __arg)
522 __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 0)));
523
524 # 412 "/usr/include/stdio.h" 3 4
525 extern int vdprintf (int __fd, const char *__restrict __fmt,
526 __gnuc_va_list __arg)
527 __attribute__ ((__format__ (__printf__, 2, 0)));
528 extern int dprintf (int __fd, const char *__restrict __fmt, ...)
529 __attribute__ ((__format__ (__printf__, 2, 3)));
530
531
532
533
534
535
536
537
538 extern int fscanf (FILE *__restrict __stream,
539 const char *__restrict __format, ...) ;
540
541
542
543
544 extern int scanf (const char *__restrict __format, ...) ;
545
546 extern int sscanf (const char *__restrict __s,
547 const char *__restrict __format, ...) __attribute__ ((__nothrow__ , __leaf__));
548 # 443 "/usr/include/stdio.h" 3 4
549 extern int fscanf (FILE *__restrict __stream, const char *__restrict __format, ...) __asm__ ("" "__isoc99_fscanf")
550
551 ;
552 extern int scanf (const char *__restrict __format, ...) __asm__ ("" "__isoc99_scanf")
553 ;
554 extern int sscanf (const char *__restrict __s, const char *__restrict __format, ...) __asm__ ("" "__isoc99_sscanf") __attribute__ ((__nothrow__ , __leaf__))
555
556 ;
557 # 463 "/usr/include/stdio.h" 3 4
558
559
560
561
562
563
564
565
566 extern int vfscanf (FILE *__restrict __s, const char *__restrict __format,
567 __gnuc_va_list __arg)
568 __attribute__ ((__format__ (__scanf__, 2, 0))) ;
569
570
571
572
573
574 extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg)
575 __attribute__ ((__format__ (__scanf__, 1, 0))) ;
576
577
578 extern int vsscanf (const char *__restrict __s,
579 const char *__restrict __format, __gnuc_va_list __arg)
580 __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__format__ (__scanf__, 2, 0)));
581 # 494 "/usr/include/stdio.h" 3 4
582 extern int vfscanf (FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vfscanf")
583
584
585
586 __attribute__ ((__format__ (__scanf__, 2, 0))) ;
587 extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vscanf")
588
589 __attribute__ ((__format__ (__scanf__, 1, 0))) ;
590 extern int vsscanf (const char *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vsscanf") __attribute__ ((__nothrow__ , __leaf__))
591
592
593
594 __attribute__ ((__format__ (__scanf__, 2, 0)));
595 # 522 "/usr/include/stdio.h" 3 4
596
597
598
599
600
601
602
603
604
605 extern int fgetc (FILE *__stream);
606 extern int getc (FILE *__stream);
607
608
609
610
611
612 extern int getchar (void);
613
614 # 550 "/usr/include/stdio.h" 3 4
615 extern int getc_unlocked (FILE *__stream);
616 extern int getchar_unlocked (void);
617 # 561 "/usr/include/stdio.h" 3 4
618 extern int fgetc_unlocked (FILE *__stream);
619
620
621
622
623
624
625
626
627
628
629
630 extern int fputc (int __c, FILE *__stream);
631 extern int putc (int __c, FILE *__stream);
632
633
634
635
636
637 extern int putchar (int __c);
638
639 # 594 "/usr/include/stdio.h" 3 4
640 extern int fputc_unlocked (int __c, FILE *__stream);
641
642
643
644
645
646
647
648 extern int putc_unlocked (int __c, FILE *__stream);
649 extern int putchar_unlocked (int __c);
650
651
652
653
654
655
656 extern int getw (FILE *__stream);
657
658
659 extern int putw (int __w, FILE *__stream);
660
661
662
663
664
665
666
667
668 extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
669 ;
670 # 638 "/usr/include/stdio.h" 3 4
671 extern char *gets (char *__s) __attribute__ ((__deprecated__));
672
673
674 # 665 "/usr/include/stdio.h" 3 4
675 extern __ssize_t __getdelim (char **__restrict __lineptr,
676 size_t *__restrict __n, int __delimiter,
677 FILE *__restrict __stream) ;
678 extern __ssize_t getdelim (char **__restrict __lineptr,
679 size_t *__restrict __n, int __delimiter,
680 FILE *__restrict __stream) ;
681
682
683
684
685
686
687
688 extern __ssize_t getline (char **__restrict __lineptr,
689 size_t *__restrict __n,
690 FILE *__restrict __stream) ;
691
692
693
694
695
696
697
698
699 extern int fputs (const char *__restrict __s, FILE *__restrict __stream);
700
701
702
703
704
705 extern int puts (const char *__s);
706
707
708
709
710
711
712 extern int ungetc (int __c, FILE *__stream);
713
714
715
716
717
718
719 extern size_t fread (void *__restrict __ptr, size_t __size,
720 size_t __n, FILE *__restrict __stream) ;
721
722
723
724
725 extern size_t fwrite (const void *__restrict __ptr, size_t __size,
726 size_t __n, FILE *__restrict __s);
727
728 # 737 "/usr/include/stdio.h" 3 4
729 extern size_t fread_unlocked (void *__restrict __ptr, size_t __size,
730 size_t __n, FILE *__restrict __stream) ;
731 extern size_t fwrite_unlocked (const void *__restrict __ptr, size_t __size,
732 size_t __n, FILE *__restrict __stream);
733
734
735
736
737
738
739
740
741 extern int fseek (FILE *__stream, long int __off, int __whence);
742
743
744
745
746 extern long int ftell (FILE *__stream) ;
747
748
749
750
751 extern void rewind (FILE *__stream);
752
753 # 773 "/usr/include/stdio.h" 3 4
754 extern int fseeko (FILE *__stream, __off_t __off, int __whence);
755
756
757
758
759 extern __off_t ftello (FILE *__stream) ;
760 # 792 "/usr/include/stdio.h" 3 4
761
762
763
764
765
766
767 extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos);
768
769
770
771
772 extern int fsetpos (FILE *__stream, const fpos_t *__pos);
773 # 815 "/usr/include/stdio.h" 3 4
774
775 # 824 "/usr/include/stdio.h" 3 4
776
777
778 extern void clearerr (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
779
780 extern int feof (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
781
782 extern int ferror (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
783
784
785
786
787 extern void clearerr_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
788 extern int feof_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
789 extern int ferror_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
790
791
792
793
794
795
796
797
798 extern void perror (const char *__s);
799
800
801
802
803
804
805 # 1 "/usr/include/i386-linux-gnu/bits/sys_errlist.h" 1 3 4
806 # 26 "/usr/include/i386-linux-gnu/bits/sys_errlist.h" 3 4
807 extern int sys_nerr;
808 extern const char *const sys_errlist[];
809 # 854 "/usr/include/stdio.h" 2 3 4
810
811
812
813
814 extern int fileno (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
815
816
817
818
819 extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
820 # 873 "/usr/include/stdio.h" 3 4
821 extern FILE *popen (const char *__command, const char *__modes) ;
822
823
824
825
826
827 extern int pclose (FILE *__stream);
828
829
830
831
832
833 extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
834 # 913 "/usr/include/stdio.h" 3 4
835 extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
836
837
838
839 extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
840
841
842 extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
843 # 943 "/usr/include/stdio.h" 3 4
844
845 # 3 "main.c" 2
846
847 extern int add(int a, int b);
848 extern int mul(int a, int b);
849
850 int main(void)
851 {
852 int a = 10, b = 5;
853 int result;
854
855 result = add(a, mul(a, b));
856 printf("result = %d\n", result);
857 return 0;
858 }
output

当然,我们也可以使用接下来要介绍的-o命令来指定输出文件名称,格式如下:

gcc -E source.c -o source.i

使用该命令对main.c进行预处理,得到的main.i文件内容与之前重定向输出得到的output文件的内容完全相同。

 

2.4 -o选项

  该选项(小写O)用于将输入文件编译后输出指定名称的文件。该选项有两种使用方法,第一种是紧跟gcc命令之后:

gcc -o app source1.c source2.c source3.c

那么,编译我们的测试程序可以使用下面的方式:

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -o app *.c
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ls
app
main.c test1.c test2.c
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ./app
result
= 60

还有另外一种方式,即-o选项放置在最后:

gcc source1.c source2.c source3.c -o app 

这种方式的逻辑性更强,语义可以理解为编译C语言源文件得到最终的可执行程序app,使用这种方式编译我们的测试程序过程如下:

xiaomanon@xiaomanon-machine:~/Documents/c_code$ rm app 
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ gcc test1.c test2.c main.c -o app
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ls
app
main.c test1.c test2.c
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ./app
result
= 60

 

此外,此选项很多时候用作链接多个目标文件的时候,我们可能需要先对不同的源文件进行相应的操作来得到目标文件*.o,然后在最后将这些目标文件链接成一个可执行文件。

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -c *.c
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ls
main.c main.o test1.c test1.o test2.c test2.o
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ gcc main.o test1.o test2.o -o app
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ls
app
main.c main.o test1.c test1.o test2.c test2.o
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ./app
result
= 60

 

2.5 -I选项

  该选项用于指定包含的头文件的目录,这一点对于大型的代码组织来说是很有用的。

 

2.6 -g选项

  该选项用来生成可以被gdb调试器使用的调试信息。只有使用了该选项后生成的可执行文件才带有程序中引用的符号表,这是gdb调试程序才能对可执行程序进行调试。

xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc *.c -o app
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ll app
-rwxrwxr-x 1 xiaomanon xiaomanon 7381 12月 29 15:23 app*
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ gcc -g *.c -o app
xiaomanon@xiaomanon
-machine:~/Documents/c_code$ ll app
-rwxrwxr-x 1 xiaomanon xiaomanon 8825 12月 29 15:23 app*

以上命令分别生成了不带调试信息的可执行文件和带有调试信息的可执行文件,并对比了两者的文件大小,可以看出使用的-g选项生成的可执行文件明显要比没有使用-g选项的可执行文件大。