zoukankan      html  css  js  c++  java
  • 5分钟理解编译系统

      本文以一个C语言版的hello world例子阐述编译系统四个阶段的工作内容。源程序hello.c如下:

    #include <stdio.h>
    
    int main() {
        printf("hello world!
    ");
    }

      作为一个精通各种语言的hello world的程序员,我相信你一定看得懂上面这段C代码。总所周知,像C语言这类的编译语言,都是将人类可读的源代码“编译”成机器能识别的“机器代码”,然后方能执行的。而我们通常所说的“编译”,实际上是指的是编译系统,一共包含4个阶段。即:预处理,编译,汇编,链接。而正是这四个阶段所需要的预处理器、编译器、汇编器、链接器构成了编译系统(compilation system)。下图是hello.c经过“编译”成为可执行的目标程序的过程示意图,接下来,将围绕此图阐述各个阶段的工作内容。

    1. 预处理阶段

      预处理器(cpp)根据以字符#号开头的命令,修改原始的c程序。比如hello.c中的第一行#include <stdio.h>命令告诉预处理器读取系统头文件stdio.h的内容,并把它直接插入到程序文本中,结果得到了另一个C程序,通常是以.i为扩展名。在Linux下我们用GCC命令:

    gcc -E hello.c -o hello.i

    得到一个hello.i文件,然后查看文件内容如下:

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

    该程序依然是C语言程序,只不过多了头文件stdio.h的内容。

    2. 编译阶段

      编译器(ccl)将文本文件hello.i翻译成文本文件hello.s,它包含一个汇编语言程序。汇编语言中每条语句都以一种标准的文本格式确切地描述了一条低级机器语言指令。其实汇编语言是非常有用的,它为所有的高级语言提供了一种通用的输出语言。比如C编译器和Fortran编译器产生的输出文件用的都是一样的汇编语言。在Linux下,我们用命令:

    gcc -S hello.i -o hello.s

    得到一个hello.s汇编程序,内容如下:

        .file    "hello.c"
        .section    .rodata
    .LC0:
        .string    "hello world!"
        .text
        .globl    main
        .type    main, @function
    main:
    .LFB0:
        .cfi_startproc
        pushq    %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $.LC0, %edi
        call    puts
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size    main, .-main
        .ident    "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-11)"
        .section    .note.GNU-stack,"",@progbits
    hello.s

    3. 汇编阶段

      汇编器(as)将hello.s翻译成机器语言指令,把这些指令打包成一种叫做可定位目标程序的格式,并将结果保存在目标文件hello.o中,hello.o是一个二进制文件,它的字节编码是“机器语言指令”而不是“字符”,所以,我们用文本编辑器打开hello.o文件看到是回事一堆乱码。使用gcc命令:

    gcc -c hello.s -o hello.o

    将得到hello.o文件,用vim打开看一下是如下乱码:

    4. 链接阶段

      我们注意到,hello.c中有一个printf函数,它是每个C编译器都会提供的标准库中的一个函数。printf函数存在于一个名为printf.o的单独的预编译好的目标文件中,而这个文件必须以某种方式合并到我们的hello.o程序中。链接器(ld)就是负责处理这种合并。最后得到hello文件,一个可执行目标文件(可执行文件),可被加载到内存中,由系统执行。使用命令:

    gcc hello.o -o hello

     得到hello文件,内容如下:

      自此,编译系统的整个过程大致如此。总结一下,从源程序到目标文件(可执行文件)的转化是通过编译系统完成的,编译系统包含四个阶段:预处理,编译,汇编,链接。一般的编译驱动程序如GCC都实现了编译系统的所有功能,我们用编译驱动程序直接就可以实现源程序到目标文件的转化。

     

  • 相关阅读:
    qt运行编译按钮居然是灰色的
    suse linux服务器的常用命令
    windows 防火墙的bug
    烦恼核心
    System.Data.OleDb.OleDbException (0x80004005) 的问题
    c#利用批处理清理大目录
    Spider Studio 社区信息
    示例
    示例
    Spider Studio 新版本 (20140225)
  • 原文地址:https://www.cnblogs.com/zingp/p/7485074.html
Copyright © 2011-2022 走看看