GCC编译器入门
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的编译选项非常多,现在有上千个,但是我们常用的并不多,下面我们只介绍其中非常实用的几个。
在这之前,我们先编写下面的几个源文件,以备测试只用。
- //main.c
- #include <stdio.h>
- extern int add(int a, int b);
- extern int mul(int a, int b);
- int main(void)
- {
- int a = , b = ;
- int result;
- result = add(a, mul(a, b));
- printf("result = %d\n", result);
- return ;
- }
main.c
- //test1.c
- int add(int a, int b)
- {
- return a+b;
- }
test1.c
- //test2.c
- int mul(int a, int b)
- {
- return a*b;
- }
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
我们也可以查看生成的汇编语言代码:
- .file "test1.c"
- .text
- .globl add
- .type add, @function
- add:
- .LFB0:
- .cfi_startproc
- pushl %ebp
- .cfi_def_cfa_offset
- .cfi_offset , -
- movl %esp, %ebp
- .cfi_def_cfa_register
- movl (%ebp), %eax
- movl (%ebp), %edx
- addl %edx, %eax
- popl %ebp
- .cfi_restore
- .cfi_def_cfa ,
- ret
- .cfi_endproc
- .LFE0:
- .size add, .-add
- .ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
- .section .note.GNU-stack,"",@progbits
test1.s
2.3 -E选项
该选项对C语言源文件进行预处理,但是并不编译该程序。对于一般的预处理问题(比如,宏的展开问题、文件的包含问题等),可以使用这个选项进行查看。另外,如果直接使用此选项,程序会将预处理结果直接输出到终端,不便于查看,因此,一般可以使用重定向将程序输出结果保存到一个文本文件中,格式如下:
- gcc -E source.c > output
如果我们对main.c执行预编译,得到的output文件内容如下:
- # "main.c"
- # "<command-line>"
- # "/usr/include/stdc-predef.h"
- # "<command-line>"
- # "main.c"
- # "/usr/include/stdio.h"
- # "/usr/include/stdio.h"
- # "/usr/include/features.h"
- # "/usr/include/features.h"
- # "/usr/include/i386-linux-gnu/sys/cdefs.h"
- # "/usr/include/i386-linux-gnu/sys/cdefs.h"
- # "/usr/include/i386-linux-gnu/bits/wordsize.h"
- # "/usr/include/i386-linux-gnu/sys/cdefs.h"
- # "/usr/include/features.h"
- # "/usr/include/features.h"
- # "/usr/include/i386-linux-gnu/gnu/stubs.h"
- # "/usr/include/i386-linux-gnu/gnu/stubs-32.h"
- # "/usr/include/i386-linux-gnu/gnu/stubs.h"
- # "/usr/include/features.h"
- # "/usr/include/stdio.h"
- # "/usr/lib/gcc/i686-linux-gnu/4.8/include/stddef.h"
- # "/usr/lib/gcc/i686-linux-gnu/4.8/include/stddef.h"
- typedef unsigned int size_t;
- # "/usr/include/stdio.h"
- # "/usr/include/i386-linux-gnu/bits/types.h"
- # "/usr/include/i386-linux-gnu/bits/types.h"
- # "/usr/include/i386-linux-gnu/bits/wordsize.h"
- # "/usr/include/i386-linux-gnu/bits/types.h"
- typedef unsigned char __u_char;
- typedef unsigned short int __u_short;
- typedef unsigned int __u_int;
- typedef unsigned long int __u_long;
- typedef signed char __int8_t;
- typedef unsigned char __uint8_t;
- typedef signed short int __int16_t;
- typedef unsigned short int __uint16_t;
- typedef signed int __int32_t;
- typedef unsigned int __uint32_t;
- __extension__ typedef signed long long int __int64_t;
- __extension__ typedef unsigned long long int __uint64_t;
- __extension__ typedef long long int __quad_t;
- __extension__ typedef unsigned long long int __u_quad_t;
- # "/usr/include/i386-linux-gnu/bits/types.h"
- # "/usr/include/i386-linux-gnu/bits/typesizes.h"
- # "/usr/include/i386-linux-gnu/bits/types.h"
- __extension__ typedef __u_quad_t __dev_t;
- __extension__ typedef unsigned int __uid_t;
- __extension__ typedef unsigned int __gid_t;
- __extension__ typedef unsigned long int __ino_t;
- __extension__ typedef __u_quad_t __ino64_t;
- __extension__ typedef unsigned int __mode_t;
- __extension__ typedef unsigned int __nlink_t;
- __extension__ typedef long int __off_t;
- __extension__ typedef __quad_t __off64_t;
- __extension__ typedef int __pid_t;
- __extension__ typedef struct { int __val[]; } __fsid_t;
- __extension__ typedef long int __clock_t;
- __extension__ typedef unsigned long int __rlim_t;
- __extension__ typedef __u_quad_t __rlim64_t;
- __extension__ typedef unsigned int __id_t;
- __extension__ typedef long int __time_t;
- __extension__ typedef unsigned int __useconds_t;
- __extension__ typedef long int __suseconds_t;
- __extension__ typedef int __daddr_t;
- __extension__ typedef int __key_t;
- __extension__ typedef int __clockid_t;
- __extension__ typedef void * __timer_t;
- __extension__ typedef long int __blksize_t;
- __extension__ typedef long int __blkcnt_t;
- __extension__ typedef __quad_t __blkcnt64_t;
- __extension__ typedef unsigned long int __fsblkcnt_t;
- __extension__ typedef __u_quad_t __fsblkcnt64_t;
- __extension__ typedef unsigned long int __fsfilcnt_t;
- __extension__ typedef __u_quad_t __fsfilcnt64_t;
- __extension__ typedef int __fsword_t;
- __extension__ typedef int __ssize_t;
- __extension__ typedef long int __syscall_slong_t;
- __extension__ typedef unsigned long int __syscall_ulong_t;
- typedef __off64_t __loff_t;
- typedef __quad_t *__qaddr_t;
- typedef char *__caddr_t;
- __extension__ typedef int __intptr_t;
- __extension__ typedef unsigned int __socklen_t;
- # "/usr/include/stdio.h"
- # "/usr/include/stdio.h"
- struct _IO_FILE;
- typedef struct _IO_FILE FILE;
- # "/usr/include/stdio.h"
- typedef struct _IO_FILE __FILE;
- # "/usr/include/stdio.h"
- # "/usr/include/libio.h"
- # "/usr/include/libio.h"
- # "/usr/include/_G_config.h"
- # "/usr/include/_G_config.h"
- # "/usr/lib/gcc/i686-linux-gnu/4.8/include/stddef.h"
- # "/usr/include/_G_config.h"
- # "/usr/include/wchar.h"
- # "/usr/include/wchar.h"
- typedef struct
- {
- int __count;
- union
- {
- unsigned int __wch;
- char __wchb[];
- } __value;
- } __mbstate_t;
- # "/usr/include/_G_config.h"
- typedef struct
- {
- __off_t __pos;
- __mbstate_t __state;
- } _G_fpos_t;
- typedef struct
- {
- __off64_t __pos;
- __mbstate_t __state;
- } _G_fpos64_t;
- # "/usr/include/libio.h"
- # "/usr/include/libio.h"
- # "/usr/lib/gcc/i686-linux-gnu/4.8/include/stdarg.h"
- # "/usr/lib/gcc/i686-linux-gnu/4.8/include/stdarg.h"
- typedef __builtin_va_list __gnuc_va_list;
- # "/usr/include/libio.h"
- # "/usr/include/libio.h"
- struct _IO_jump_t; struct _IO_FILE;
- # "/usr/include/libio.h"
- typedef void _IO_lock_t;
- struct _IO_marker {
- struct _IO_marker *_next;
- struct _IO_FILE *_sbuf;
- int _pos;
- # "/usr/include/libio.h"
- };
- enum __codecvt_result
- {
- __codecvt_ok,
- __codecvt_partial,
- __codecvt_error,
- __codecvt_noconv
- };
- # "/usr/include/libio.h"
- struct _IO_FILE {
- int _flags;
- char* _IO_read_ptr;
- char* _IO_read_end;
- char* _IO_read_base;
- char* _IO_write_base;
- char* _IO_write_ptr;
- char* _IO_write_end;
- char* _IO_buf_base;
- char* _IO_buf_end;
- char *_IO_save_base;
- char *_IO_backup_base;
- char *_IO_save_end;
- struct _IO_marker *_markers;
- struct _IO_FILE *_chain;
- int _fileno;
- int _flags2;
- __off_t _old_offset;
- unsigned short _cur_column;
- signed char _vtable_offset;
- char _shortbuf[];
- _IO_lock_t *_lock;
- # "/usr/include/libio.h"
- __off64_t _offset;
- # "/usr/include/libio.h"
- void *__pad1;
- void *__pad2;
- void *__pad3;
- void *__pad4;
- size_t __pad5;
- int _mode;
- char _unused2[ * sizeof (int) - * sizeof (void *) - sizeof (size_t)];
- };
- typedef struct _IO_FILE _IO_FILE;
- struct _IO_FILE_plus;
- extern struct _IO_FILE_plus _IO_2_1_stdin_;
- extern struct _IO_FILE_plus _IO_2_1_stdout_;
- extern struct _IO_FILE_plus _IO_2_1_stderr_;
- # "/usr/include/libio.h"
- typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes);
- typedef __ssize_t __io_write_fn (void *__cookie, const char *__buf,
- size_t __n);
- typedef int __io_seek_fn (void *__cookie, __off64_t *__pos, int __w);
- typedef int __io_close_fn (void *__cookie);
- # "/usr/include/libio.h"
- extern int __underflow (_IO_FILE *);
- extern int __uflow (_IO_FILE *);
- extern int __overflow (_IO_FILE *, int);
- # "/usr/include/libio.h"
- extern int _IO_getc (_IO_FILE *__fp);
- extern int _IO_putc (int __c, _IO_FILE *__fp);
- extern int _IO_feof (_IO_FILE *__fp) __attribute__ ((__nothrow__ , __leaf__));
- extern int _IO_ferror (_IO_FILE *__fp) __attribute__ ((__nothrow__ , __leaf__));
- extern int _IO_peekc_locked (_IO_FILE *__fp);
- extern void _IO_flockfile (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__));
- extern void _IO_funlockfile (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__));
- extern int _IO_ftrylockfile (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__));
- # "/usr/include/libio.h"
- extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict,
- __gnuc_va_list, int *__restrict);
- extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict,
- __gnuc_va_list);
- extern __ssize_t _IO_padn (_IO_FILE *, int, __ssize_t);
- extern size_t _IO_sgetn (_IO_FILE *, void *, size_t);
- extern __off64_t _IO_seekoff (_IO_FILE *, __off64_t, int, int);
- extern __off64_t _IO_seekpos (_IO_FILE *, __off64_t, int);
- extern void _IO_free_backup_area (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__));
- # "/usr/include/stdio.h"
- typedef __gnuc_va_list va_list;
- # "/usr/include/stdio.h"
- typedef __off_t off_t;
- # "/usr/include/stdio.h"
- typedef __ssize_t ssize_t;
- typedef _G_fpos_t fpos_t;
- # "/usr/include/stdio.h"
- # "/usr/include/i386-linux-gnu/bits/stdio_lim.h"
- # "/usr/include/stdio.h"
- extern struct _IO_FILE *stdin;
- extern struct _IO_FILE *stdout;
- extern struct _IO_FILE *stderr;
- extern int remove (const char *__filename) __attribute__ ((__nothrow__ , __leaf__));
- extern int rename (const char *__old, const char *__new) __attribute__ ((__nothrow__ , __leaf__));
- extern int renameat (int __oldfd, const char *__old, int __newfd,
- const char *__new) __attribute__ ((__nothrow__ , __leaf__));
- extern FILE *tmpfile (void) ;
- # "/usr/include/stdio.h"
- extern char *tmpnam (char *__s) __attribute__ ((__nothrow__ , __leaf__)) ;
- extern char *tmpnam_r (char *__s) __attribute__ ((__nothrow__ , __leaf__)) ;
- # "/usr/include/stdio.h"
- extern char *tempnam (const char *__dir, const char *__pfx)
- __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;
- extern int fclose (FILE *__stream);
- extern int fflush (FILE *__stream);
- # "/usr/include/stdio.h"
- extern int fflush_unlocked (FILE *__stream);
- # "/usr/include/stdio.h"
- extern FILE *fopen (const char *__restrict __filename,
- const char *__restrict __modes) ;
- extern FILE *freopen (const char *__restrict __filename,
- const char *__restrict __modes,
- FILE *__restrict __stream) ;
- # "/usr/include/stdio.h"
- # "/usr/include/stdio.h"
- extern FILE *fdopen (int __fd, const char *__modes) __attribute__ ((__nothrow__ , __leaf__)) ;
- # "/usr/include/stdio.h"
- extern FILE *fmemopen (void *__s, size_t __len, const char *__modes)
- __attribute__ ((__nothrow__ , __leaf__)) ;
- extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __attribute__ ((__nothrow__ , __leaf__)) ;
- extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __attribute__ ((__nothrow__ , __leaf__));
- extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf,
- int __modes, size_t __n) __attribute__ ((__nothrow__ , __leaf__));
- extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf,
- size_t __size) __attribute__ ((__nothrow__ , __leaf__));
- extern void setlinebuf (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
- extern int fprintf (FILE *__restrict __stream,
- const char *__restrict __format, ...);
- extern int printf (const char *__restrict __format, ...);
- extern int sprintf (char *__restrict __s,
- const char *__restrict __format, ...) __attribute__ ((__nothrow__));
- extern int vfprintf (FILE *__restrict __s, const char *__restrict __format,
- __gnuc_va_list __arg);
- extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg);
- extern int vsprintf (char *__restrict __s, const char *__restrict __format,
- __gnuc_va_list __arg) __attribute__ ((__nothrow__));
- extern int snprintf (char *__restrict __s, size_t __maxlen,
- const char *__restrict __format, ...)
- __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, , )));
- extern int vsnprintf (char *__restrict __s, size_t __maxlen,
- const char *__restrict __format, __gnuc_va_list __arg)
- __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, , )));
- # "/usr/include/stdio.h"
- extern int vdprintf (int __fd, const char *__restrict __fmt,
- __gnuc_va_list __arg)
- __attribute__ ((__format__ (__printf__, , )));
- extern int dprintf (int __fd, const char *__restrict __fmt, ...)
- __attribute__ ((__format__ (__printf__, , )));
- extern int fscanf (FILE *__restrict __stream,
- const char *__restrict __format, ...) ;
- extern int scanf (const char *__restrict __format, ...) ;
- extern int sscanf (const char *__restrict __s,
- const char *__restrict __format, ...) __attribute__ ((__nothrow__ , __leaf__));
- # "/usr/include/stdio.h"
- extern int fscanf (FILE *__restrict __stream, const char *__restrict __format, ...) __asm__ ("" "__isoc99_fscanf")
- ;
- extern int scanf (const char *__restrict __format, ...) __asm__ ("" "__isoc99_scanf")
- ;
- extern int sscanf (const char *__restrict __s, const char *__restrict __format, ...) __asm__ ("" "__isoc99_sscanf") __attribute__ ((__nothrow__ , __leaf__))
- ;
- # "/usr/include/stdio.h"
- extern int vfscanf (FILE *__restrict __s, const char *__restrict __format,
- __gnuc_va_list __arg)
- __attribute__ ((__format__ (__scanf__, , ))) ;
- extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg)
- __attribute__ ((__format__ (__scanf__, , ))) ;
- extern int vsscanf (const char *__restrict __s,
- const char *__restrict __format, __gnuc_va_list __arg)
- __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__format__ (__scanf__, , )));
- # "/usr/include/stdio.h"
- extern int vfscanf (FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vfscanf")
- __attribute__ ((__format__ (__scanf__, , ))) ;
- extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vscanf")
- __attribute__ ((__format__ (__scanf__, , ))) ;
- extern int vsscanf (const char *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vsscanf") __attribute__ ((__nothrow__ , __leaf__))
- __attribute__ ((__format__ (__scanf__, , )));
- # "/usr/include/stdio.h"
- extern int fgetc (FILE *__stream);
- extern int getc (FILE *__stream);
- extern int getchar (void);
- # "/usr/include/stdio.h"
- extern int getc_unlocked (FILE *__stream);
- extern int getchar_unlocked (void);
- # "/usr/include/stdio.h"
- extern int fgetc_unlocked (FILE *__stream);
- extern int fputc (int __c, FILE *__stream);
- extern int putc (int __c, FILE *__stream);
- extern int putchar (int __c);
- # "/usr/include/stdio.h"
- extern int fputc_unlocked (int __c, FILE *__stream);
- extern int putc_unlocked (int __c, FILE *__stream);
- extern int putchar_unlocked (int __c);
- extern int getw (FILE *__stream);
- extern int putw (int __w, FILE *__stream);
- extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
- ;
- # "/usr/include/stdio.h"
- extern char *gets (char *__s) __attribute__ ((__deprecated__));
- # "/usr/include/stdio.h"
- extern __ssize_t __getdelim (char **__restrict __lineptr,
- size_t *__restrict __n, int __delimiter,
- FILE *__restrict __stream) ;
- extern __ssize_t getdelim (char **__restrict __lineptr,
- size_t *__restrict __n, int __delimiter,
- FILE *__restrict __stream) ;
- extern __ssize_t getline (char **__restrict __lineptr,
- size_t *__restrict __n,
- FILE *__restrict __stream) ;
- extern int fputs (const char *__restrict __s, FILE *__restrict __stream);
- extern int puts (const char *__s);
- extern int ungetc (int __c, FILE *__stream);
- extern size_t fread (void *__restrict __ptr, size_t __size,
- size_t __n, FILE *__restrict __stream) ;
- extern size_t fwrite (const void *__restrict __ptr, size_t __size,
- size_t __n, FILE *__restrict __s);
- # "/usr/include/stdio.h"
- extern size_t fread_unlocked (void *__restrict __ptr, size_t __size,
- size_t __n, FILE *__restrict __stream) ;
- extern size_t fwrite_unlocked (const void *__restrict __ptr, size_t __size,
- size_t __n, FILE *__restrict __stream);
- extern int fseek (FILE *__stream, long int __off, int __whence);
- extern long int ftell (FILE *__stream) ;
- extern void rewind (FILE *__stream);
- # "/usr/include/stdio.h"
- extern int fseeko (FILE *__stream, __off_t __off, int __whence);
- extern __off_t ftello (FILE *__stream) ;
- # "/usr/include/stdio.h"
- extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos);
- extern int fsetpos (FILE *__stream, const fpos_t *__pos);
- # "/usr/include/stdio.h"
- # "/usr/include/stdio.h"
- extern void clearerr (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
- extern int feof (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
- extern int ferror (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
- extern void clearerr_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
- extern int feof_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
- extern int ferror_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
- extern void perror (const char *__s);
- # "/usr/include/i386-linux-gnu/bits/sys_errlist.h"
- # "/usr/include/i386-linux-gnu/bits/sys_errlist.h"
- extern int sys_nerr;
- extern const char *const sys_errlist[];
- # "/usr/include/stdio.h"
- extern int fileno (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
- extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
- # "/usr/include/stdio.h"
- extern FILE *popen (const char *__command, const char *__modes) ;
- extern int pclose (FILE *__stream);
- extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
- # "/usr/include/stdio.h"
- extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
- extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
- extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
- # "/usr/include/stdio.h"
- # "main.c"
- extern int add(int a, int b);
- extern int mul(int a, int b);
- int main(void)
- {
- int a = , b = ;
- int result;
- result = add(a, mul(a, b));
- printf("result = %d\n", result);
- return ;
- }
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 =
还有另外一种方式,即-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 =
此外,此选项很多时候用作链接多个目标文件的时候,我们可能需要先对不同的源文件进行相应的操作来得到目标文件*.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 =
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 xiaomanon xiaomanon 12月 : app*
- xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc -g *.c -o app
- xiaomanon@xiaomanon-machine:~/Documents/c_code$ ll app
- -rwxrwxr-x xiaomanon xiaomanon 8825 12月 : app*
以上命令分别生成了不带调试信息的可执行文件和带有调试信息的可执行文件,并对比了两者的文件大小,可以看出使用的-g选项生成的可执行文件明显要比没有使用-g选项的可执行文件大。
GCC编译器入门的更多相关文章
- C语言的本质(33)——GCC编译器入门
GCC(GNU CompilerCollection,GNU编译器套装),是由 GNU 开发的编程语言编译器.它是以GPL许可证所发行的自由软件,也是 GNU计划的关键部分.GCC原本作为GNU操作系 ...
- GCC编译器入门[转载]
GCC编译器(GNU C Compiler)是GNU组织的一款开源 编译器,它是Linux环境下的默认C语言编译器.它处理能够高效的编译C语言以外,还可以编译其他语言.并且,现在的GCC已经不光包括编 ...
- GCC编译器基础入门
导语 GCC(GNU Compiler Collection,GNU 编译器套件) 是由 GNU 开发的编程语言编译器,支持C.C++.Objective-C.Fortran.Java.Ada和Go语 ...
- Linux环境下的GCC编译器与GDB调试工具介绍
假如现在我们有如下代码需要编译运行和调试.文件名为:test.c #include <stdio.h> int main() { int day, month, year, sum, le ...
- 在CentOS 7.2下升级gcc编译器的版本
默认情况下,CentOS 7.2预装的gcc版本是4.8.x,通过执行命令 gcc -v 可以看到,一般情况下这个版本的编译器已经满足需要了,但是某些特殊的时候为了支持C++更高的特性,需要对gcc编 ...
- C语言的编译过程、安装gcc编译器以及设置环境变量
以我对C语言编译过程的了解,我用了一点时间画了一个图,提供给大家参考一下,希望有些能对您的问题提上帮助. 前几天刚初步学习了C语言的编译过程,感触挺深的.在C语言中头文件其实起了一个很大的作用. 1. ...
- 利用GCC编译器生成动态链接库和静态链接库
转载请标明:http://www.cnblogs.com/winifred-tang94/ 1.编译过程 gcc –fPIC –c xxx.c 其中-fPIC是通知gcc编译器产生位置独立的目标代码. ...
- GCC编译器编译链接
在gcc编译器环境下,常见的文件扩展名的含义如下: .c:C源程序,经过预编译后的源程序也为.c文件,它可以通过-E参数输出. .h:头文件 .s:经过编译得到的汇编程序代码,它可以通过-S参数输出. ...
- Linux安装gcc编译器详解
本人使用的是CentOS 6.5 64位系统,由于在安装系统的时候并没有勾选安装gcc编译器,因此需要自行安装gcc编译器. 使用yum安装gcc 对于配备了yum的Linux发行版而言,安装gcc编 ...
随机推荐
- mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication的解决方法
直接命令行操作没有问题,但是PHP连接就会报上面的错误. SET old_passwords =0; USE mysql; UPDATE user SET password =PASSWORD('yo ...
- [Effective C++ --010]令赋值操作符返回一个reference to *this
差不多最经典的就是这个了: x = y = z = ; 解读为: x = (y = ( z = )); 如果没有返回值,上述代码就不能通过编译. 其实看到标题就差不多明白这一条了,但是为什么连续赋值时 ...
- 信号之system函数
在http://www.cnblogs.com/nufangrensheng/p/3512291.html中已经有了一个system函数的实现,但是该版本并不执行任何信号处理.POSIX.1要求sys ...
- Tomcat 配置 Probe 监控
转至:http://9771104.blog.163.com/blog/static/19446622009811112836524/ 手上接触Tomcat的项目越来越多,虽说tomcat的manag ...
- Supervised Learning-Regression
假设我们有一张房子属性及其价格之间的关系表(如下图所示) ,根据这些数据如何估计其他房子的价格?我们的第一个反应肯定是参考属性相似的房子的价格.在属性较少时这个方法还行得通,属性太复杂时就不那么简单了 ...
- Regular Expressions --正则表达式官方教程
http://docs.oracle.com/javase/tutorial/essential/regex/index.html This lesson explains how to use th ...
- ajax的一部分知识
jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为String类型的参数,请求方式(p ...
- update目标在查询返回结果集中的解决方案
示例: students为学生信息表 Score为成绩表 两个表通过学生号关联 要求:将总成绩小于100的学生名称改为‘天才’ sql如下: error提示:update目标不能在查询返回结果集中 ...
- java算法小知识练习
偶尔翻开了以前的练习题,不自觉又想随手敲一遍,虽然有些思想依然是那么老套,但毕竟也算是对知识的巩固 了. 一.题目:有1.2.3.4四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 具体 ...
- arguments 函数内部属性
1.arguments 是在function方法里面的,是实参数组,用法是挺多的,下面来记录一下 2.利用arguments实现方法的重载 //01.使用argument模拟方法重载 function ...