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的编译选项非常多,现在有上千个,但是我们常用的并不多,下面我们只介绍其中非常实用的几个。
在这之前,我们先编写下面的几个源文件,以备测试只用。
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 }
1 //test1.c 2 int add(int a, int b) 3 { 4 return a+b; 5 }
1 //test2.c 2 int mul(int a, int b) 3 { 4 return a*b; 5 }
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
我们也可以查看生成的汇编语言代码:
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
2.3 -E选项
该选项对C语言源文件进行预处理,但是并不编译该程序。对于一般的预处理问题(比如,宏的展开问题、文件的包含问题等),可以使用这个选项进行查看。另外,如果直接使用此选项,程序会将预处理结果直接输出到终端,不便于查看,因此,一般可以使用重定向将程序输出结果保存到一个文本文件中,格式如下:
gcc -E source.c > output
如果我们对main.c执行预编译,得到的output文件内容如下:
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 }
当然,我们也可以使用接下来要介绍的-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选项的可执行文件大。