C 语言学习的第 03 课:你的 idea 是怎么变成能够执行的程序的

在上一篇文章中,我们说到,C 语言系统应该由程序开发环境,C 语言本身和 C 语言的库组成。且同时说了程序开发环境做了“编写”,“预处理”,“编译”和“链接”这几件事情。但是细节并没有一一呈现。不知道同学们是否想过,这里都经历了一些什么呢?!

在这一篇文章中,我们就来看看“上帝说,要有光,就有了光。”是怎么实现的。假设你是上帝,想要实现“给我输出 ‘HELLO,WORLD!‘”。同学们使用的 IDE 是 C-Free 5,这里的所有操作,都以此编译器为例。假设编译器安装路径为“C:\Program Files\C-Free 5”。

1. 代码编写

同学们已经上过第一节课了,我想,编写一个“HELLO,WORLD!”一定不成问题。代码本身是这样的:

1 #include <stdio.h>
2
3 int main(void)
4 {
5     printf("HELLO,WORLD!\n");
6     return 0;
7 }

将此代码保存为“HelloWord.c”后准备下一步的处理。

2. 预处理

在保存了“HelloWord.c”文件夹中打开一个“cmd”窗口(按住 Shift 后右击选择“在此处打开命令窗口”),输入:

gcc -E HelloWorld.c -o HelloWorld.i
# 命令解释:
# 在 C-Free 5 身后,默默工作的就是这个名叫 gcc 的编译器了。
# 当输入上面的命令,紧跟其后的“-E”告知编译器想要做的是动作是仅做预处理这个动作。
# 然后后面跟随的“.c”文件告知 gcc 需要处理的文件的名称
# -o HelloWorld.i,是告诉编译器,输出一个文件,文件名就是“HelloWorld.i”
# (你看,计算机就是一个输入然后输出的系统吧)

你会发现,在此目录下生成了一个名为“HelloWorld.i”的文件,打开文件,观察内容你会发现是这样的:

  1 # 1 "HelloWorld.c"
  2 # 1 "<built-in>"
  3 # 1 "<command line>"
  4 # 1 "HelloWorld.c"
  5 # 1 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 1 3
  6 # 19 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
  7 # 1 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/_mingw.h" 1 3
  8 # 27 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/_mingw.h" 3
  9
 10 # 28 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/_mingw.h" 3
 11 # 20 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 2 3
 12
 13
 14
 15
 16
 17
 18 # 1 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stddef.h" 1 3
 19
 20
 21
 22
 23
 24 # 1 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/include/stddef.h" 1 3 4
 25 # 213 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/include/stddef.h" 3 4
 26 typedef unsigned int size_t;
 27 # 325 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/include/stddef.h" 3 4
 28 typedef short unsigned int wchar_t;
 29 # 354 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/include/stddef.h" 3 4
 30 typedef short unsigned int wint_t;
 31 # 7 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stddef.h" 2 3
 32 # 27 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 2 3
 33
 34 # 1 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdarg.h" 1 3
 35
 36
 37
 38
 39
 40 # 1 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/include/stdarg.h" 1 3 4
 41 # 44 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/include/stdarg.h" 3 4
 42 typedef __builtin_va_list __gnuc_va_list;
 43 # 7 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdarg.h" 2 3
 44 # 29 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 2 3
 45 # 129 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
 46 typedef struct _iobuf
 47 {
 48  char* _ptr;
 49  int _cnt;
 50  char* _base;
 51  int _flag;
 52  int _file;
 53  int _charbuf;
 54  int _bufsiz;
 55  char* _tmpfname;
 56 } FILE;
 57 # 154 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
 58 extern __attribute__ ((__dllimport__)) FILE _iob[];
 59 # 169 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
 60  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fopen (const char*, const char*);
 61  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) freopen (const char*, const char*, FILE*);
 62  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fflush (FILE*);
 63  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fclose (FILE*);
 64
 65  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) remove (const char*);
 66  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) rename (const char*, const char*);
 67  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) tmpfile (void);
 68  char* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) tmpnam (char*);
 69
 70
 71  char* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _tempnam (const char*, const char*);
 72  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _rmtmp(void);
 73  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _unlink (const char*);
 74
 75
 76  char* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) tempnam (const char*, const char*);
 77  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) rmtmp(void);
 78  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) unlink (const char*);
 79
 80
 81
 82  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) setvbuf (FILE*, char*, int, size_t);
 83
 84  void __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) setbuf (FILE*, char*);
 85
 86
 87
 88
 89
 90  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fprintf (FILE*, const char*, ...);
 91  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) printf (const char*, ...);
 92  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) sprintf (char*, const char*, ...);
 93  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _snprintf (char*, size_t, const char*, ...);
 94  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vfprintf (FILE*, const char*, __gnuc_va_list);
 95  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vprintf (const char*, __gnuc_va_list);
 96  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vsprintf (char*, const char*, __gnuc_va_list);
 97  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _vsnprintf (char*, size_t, const char*, __gnuc_va_list);
 98 # 216 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
 99 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) snprintf(char *, size_t, const char *, ...);
100 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vsnprintf (char *, size_t, const char *, __gnuc_va_list);
101
102 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vscanf (const char * __restrict__, __gnuc_va_list);
103 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vfscanf (FILE * __restrict__, const char * __restrict__,
104        __gnuc_va_list);
105 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vsscanf (const char * __restrict__,
106        const char * __restrict__, __gnuc_va_list);
107
108
109
110
111
112
113
114  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fscanf (FILE*, const char*, ...);
115  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) scanf (const char*, ...);
116  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) sscanf (const char*, const char*, ...);
117
118
119
120
121  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fgetc (FILE*);
122  char* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fgets (char*, int, FILE*);
123  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fputc (int, FILE*);
124  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fputs (const char*, FILE*);
125  char* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) gets (char*);
126  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) puts (const char*);
127  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) ungetc (int, FILE*);
128
129
130
131
132
133
134
135  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _filbuf (FILE*);
136  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _flsbuf (int, FILE*);
137
138
139
140 extern __inline__ int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) getc (FILE* __F)
141 {
142   return (--__F->_cnt >= 0)
143     ? (int) (unsigned char) *__F->_ptr++
144     : _filbuf (__F);
145 }
146
147 extern __inline__ int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) putc (int __c, FILE* __F)
148 {
149   return (--__F->_cnt >= 0)
150     ? (int) (unsigned char) (*__F->_ptr++ = (char)__c)
151     : _flsbuf (__c, __F);
152 }
153
154 extern __inline__ int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) getchar (void)
155 {
156   return (--(&_iob[0])->_cnt >= 0)
157     ? (int) (unsigned char) *(&_iob[0])->_ptr++
158     : _filbuf ((&_iob[0]));
159 }
160
161 extern __inline__ int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) putchar(int __c)
162 {
163   return (--(&_iob[1])->_cnt >= 0)
164     ? (int) (unsigned char) (*(&_iob[1])->_ptr++ = (char)__c)
165     : _flsbuf (__c, (&_iob[1]));}
166 # 297 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
167  size_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fread (void*, size_t, size_t, FILE*);
168  size_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fwrite (const void*, size_t, size_t, FILE*);
169
170
171
172
173
174  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fseek (FILE*, long, int);
175  long __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) ftell (FILE*);
176  void __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) rewind (FILE*);
177 # 340 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
178 typedef long long fpos_t;
179
180
181
182
183  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fgetpos (FILE*, fpos_t*);
184  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fsetpos (FILE*, const fpos_t*);
185
186
187
188
189
190  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) feof (FILE*);
191  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) ferror (FILE*);
192 # 365 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
193  void __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) clearerr (FILE*);
194  void __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) perror (const char*);
195
196
197
198
199
200
201  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _popen (const char*, const char*);
202  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _pclose (FILE*);
203
204
205  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) popen (const char*, const char*);
206  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) pclose (FILE*);
207
208
209
210
211
212  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _flushall (void);
213  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _fgetchar (void);
214  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _fputchar (int);
215  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _fdopen (int, const char*);
216  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _fileno (FILE*);
217  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _fcloseall(void);
218  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _fsopen(const char*, const char*, int);
219
220  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _getmaxstdio(void);
221  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _setmaxstdio(int);
222 # 402 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
223  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fgetchar (void);
224  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fputchar (int);
225  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fdopen (int, const char*);
226  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fileno (FILE*);
227 # 414 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
228 # 1 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/sys/types.h" 1 3
229 # 21 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/sys/types.h" 3
230 # 1 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stddef.h" 1 3
231
232
233
234
235
236 # 1 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/include/stddef.h" 1 3 4
237 # 151 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/include/stddef.h" 3 4
238 typedef int ptrdiff_t;
239 # 7 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stddef.h" 2 3
240 # 22 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/sys/types.h" 2 3
241
242
243
244
245
246 typedef long time_t;
247
248
249
250
251 typedef long long __time64_t;
252
253
254
255
256
257 typedef long _off_t;
258
259
260 typedef _off_t off_t;
261
262
263
264
265
266
267
268 typedef unsigned int _dev_t;
269
270
271
272
273
274 typedef _dev_t dev_t;
275
276
277
278
279
280
281 typedef short _ino_t;
282
283
284 typedef _ino_t ino_t;
285
286
287
288
289
290
291 typedef int _pid_t;
292
293
294 typedef _pid_t pid_t;
295
296
297
298
299
300
301 typedef unsigned short _mode_t;
302
303
304 typedef _mode_t mode_t;
305
306
307
308
309
310
311 typedef int _sigset_t;
312
313
314 typedef _sigset_t sigset_t;
315
316
317
318
319
320 typedef long _ssize_t;
321
322
323 typedef _ssize_t ssize_t;
324
325
326
327
328
329 typedef long long fpos64_t;
330
331
332
333
334 typedef long long off64_t;
335 # 415 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 2 3
336 extern __inline__ FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fopen64 (const char* filename, const char* mode)
337 {
338   return fopen (filename, mode);
339 }
340
341 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fseeko64 (FILE*, off64_t, int);
342
343
344
345
346
347
348 extern __inline__ off64_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) ftello64 (FILE * stream)
349 {
350   fpos_t pos;
351   if (fgetpos(stream, &pos))
352     return -1LL;
353   else
354    return ((off64_t) pos);
355 }
356 # 443 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
357  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fwprintf (FILE*, const wchar_t*, ...);
358  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) wprintf (const wchar_t*, ...);
359  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) swprintf (wchar_t*, const wchar_t*, ...);
360  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _snwprintf (wchar_t*, size_t, const wchar_t*, ...);
361  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vfwprintf (FILE*, const wchar_t*, __gnuc_va_list);
362  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vwprintf (const wchar_t*, __gnuc_va_list);
363  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswprintf (wchar_t*, const wchar_t*, __gnuc_va_list);
364  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _vsnwprintf (wchar_t*, size_t, const wchar_t*, __gnuc_va_list);
365  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fwscanf (FILE*, const wchar_t*, ...);
366  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) wscanf (const wchar_t*, ...);
367  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) swscanf (const wchar_t*, const wchar_t*, ...);
368  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fgetwc (FILE*);
369  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fputwc (wchar_t, FILE*);
370  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) ungetwc (wchar_t, FILE*);
371
372
373  wchar_t* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fgetws (wchar_t*, int, FILE*);
374  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fputws (const wchar_t*, FILE*);
375  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) getwc (FILE*);
376  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) getwchar (void);
377  wchar_t* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _getws (wchar_t*);
378  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) putwc (wint_t, FILE*);
379  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _putws (const wchar_t*);
380  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) putwchar (wint_t);
381  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _wfdopen(int, wchar_t *);
382  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _wfopen (const wchar_t*, const wchar_t*);
383  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _wfreopen (const wchar_t*, const wchar_t*, FILE*);
384  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _wfsopen (const wchar_t*, const wchar_t*, int);
385  wchar_t* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _wtmpnam (wchar_t*);
386  wchar_t* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _wtempnam (const wchar_t*, const wchar_t*);
387  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _wrename (const wchar_t*, const wchar_t*);
388  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _wremove (const wchar_t*);
389  void __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _wperror (const wchar_t*);
390  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _wpopen (const wchar_t*, const wchar_t*);
391
392
393
394 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) snwprintf (wchar_t* s, size_t n, const wchar_t* format, ...);
395 extern __inline__ int __attribute__((__cdecl__)) __attribute__ ((__nothrow__))
396 vsnwprintf (wchar_t* s, size_t n, const wchar_t* format, __gnuc_va_list arg)
397   { return _vsnwprintf ( s, n, format, arg);}
398 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vwscanf (const wchar_t * __restrict__, __gnuc_va_list);
399 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vfwscanf (FILE * __restrict__,
400          const wchar_t * __restrict__, __gnuc_va_list);
401 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (const wchar_t * __restrict__,
402          const wchar_t * __restrict__, __gnuc_va_list);
403 # 497 "C:/Program Files (x86)/C-Free 5/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../../include/stdio.h" 3
404  FILE* __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) wpopen (const wchar_t*, const wchar_t*);
405
406
407
408
409
410
411  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _fgetwchar (void);
412  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _fputwchar (wint_t);
413  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _getw (FILE*);
414  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) _putw (int, FILE*);
415
416
417  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fgetwchar (void);
418  wint_t __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) fputwchar (wint_t);
419  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) getw (FILE*);
420  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) putw (int, FILE*);
421 # 2 "HelloWorld.c" 2
422
423 int main(void)
424 {
425  printf("HELLO,WORLD!\n");
426  return 0;
427 }

拖动到最底部,才能够发现我们最开始写的那几行代码。但是代码又和我们之前写的似而不同:

1  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) getw (FILE*);
2  int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) putw (int, FILE*);
3 # 2 "HelloWorld.c" 2
4
5 int main(void)
6 {
7  printf("HELLO,WORLD!\n");
8  return 0;
9 }

可以发现,第一行的 #include <stdio.h> 却再也找不到了。其实,这就是预处理的功能,它会将你的代码中的 #include <XXXXXXX.h>  全部替换到,为下面的编译做准备。

需要注意的是,预处理阶段,编译器 gcc 是不做语法上的检查的,比如我们写一段貌合神离的代码:

1 #include <stdio.h>
2
3 printf("HELLO,WORLD!\n");

然后重新执行上面的命令,你会发现,依旧会生成一个看似可用的“.i”文件。

3. 编译

编译阶段,编译器 gcc 将会对之前预处理生成的“.i”文件进行语法上的检查,看其是否符合 C 语言的语法规范,当检查通过以后,就进行编译的过程。这里,将其过程分为两步来看,首先,将预处理文件翻译为汇编文件:

1 gcc -S HelloWorld.i -o helloWorld.s

然后将汇编文件编译为目标文件:

1 gcc -c HelloWorld.s -o HelloWorld.obj

这里我们再来试试之前的“李鬼”代码,看看它能否通过流程,生成汇编文件:

1 gcc -S HelloWorld.i -o helloWorld.s
2 HelloWorldError.c:3: error: syntax error before string constant
3 HelloWorldError.c:3: error: conflicting types for ‘printf‘
4 HelloWorldError.c:3: note: a parameter list with an ellipsis can‘t match an empty parameter name list declaration
5 HelloWorldError.c:3: error: conflicting types for ‘printf‘
6 HelloWorldError.c:3: note: a parameter list with an ellipsis can‘t match an empty parameter name list declaration
7 HelloWorldError.c:3: warning: data definition has no type or storage class

哎呦,出了一堆的错误唉,有此可见,编译过程是需要执行内容的检查的,以确定其符合 C 语言的语法。

4. 链接

在上一步中,生成的目标文件“.obj”虽然本身也是二进制文件,但是其本身是不可执行的,需要对其进行链接。

1 gcc helloworld.obj -o helloworld.exe

到这里,就生成可以执行的二进制文件了,赶快在终端中输入“HelloWorld”尝试运行吧:

虽然同学们可能直接在 C-Free 中仅需要点击一下按钮,后台就已经给你做了以上的这些事情,但是这里还是希望同学们能够理解这一过程(链接这一过程涉及到 C 语言库函数的事情,大家可以再扩展阅读哦)。

时间: 2024-10-03 13:45:13

C 语言学习的第 03 课:你的 idea 是怎么变成能够执行的程序的的相关文章

C 语言学习的第 05 课:C 语言基础(01)

C语言程序中的绝大部分应该记录在以.c作为扩展名的文件里,这种文件叫做C语言????程序的源文件. C语言中还包括以.h作为扩展名的文件,这种文件叫做头文件. C语言中的四则运算: 加:+ 减:- 乘:* 除:/ 取余:% C语言程序里每个计算步骤都必须用";"结束,每个用";"结束的计算步骤叫做一条语句. C语言中大括号可以用来表示一个函数,一条语句可以实现一个功能,一个函数是多个语句的集合(但是允许没有语句的函数). 每个函数有自己的名字,不同函数的名字不同.

C 语言学习的第01课:先来谈谈计算机吧

各位同学,新学期,我就是你们的助教了.我的个人信息,你们的任课老师都已经介绍过了,所以我这里也就不再啰嗦.下面,来聊聊今天的话题:“先来谈谈计算机吧”. 想必看到这个题目,你们大家一定是不愿意点击进来的,毕竟,现在的你们呐,一定都是差不多天天面对计算机的(要知道,现在你们的手机,都要比早些年的计算机要先进,性能强大很多).但是,不知道你是不是有想过和它相关的一些问题呢.比如: 当按下开关机按键以后,它是怎么进入操作系统的: 进入操作系统以后,它怎么启动第一个程序的: 软件是怎么控制硬件的(比如你

C 语言学习的第 04 课:编译器常见错误和警告

同学们可能已经开始使用 C-Free 5 写自己的程序了.但是新手编程,总是会有一些磕磕绊绊.不要紧,在这篇文章中,就主要来了解一些编程开始时经常会遇到的语法方面的问题. warning: no newline at end of file 出现此警告,不用太过于担心,仅仅是".c"文件的最后面,没有一个空行.你只需要每次写完代码后,都随手添加一个回车就可以了.至于原因,因为C-Free 5默认的编译器是 GCC,它来自于 Unix 系统,而 Unix 系统中默认的回车和 Window

JAVA学习第六十课 — UDP协议 &amp;基于多线程模拟简单的QQ聊天程序

UDP传输 UDP有发送端和接受端,有两大类,DatagramSocket.DatagramPacket 建立发送端和接收端 建立数据包 调用Socket的接收发送方法 关闭Socket 注意:发送端和接收端是两个独立的运行程序 UDP发送端演示 DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号. public static voi

关于c语言学习 谭浩强的书

2007-11-16 13:22:58|  分类: PROGRAMME |  标签: |举报 |字号大中小 订阅 广大有志于从事IT行业的同志们,在你们进入这一行之前千万请看这篇文章!太经典了!对你绝对有启发! 千万别买谭浩强和等级考试的书!!!!!! 整理别人的言论,请大家踊跃讨论!!!!!!!!!!!! 1:书皮上面有那么多的牛人题词,估计也许是自己的水平太低. 2:ANSI只给了两种方式:int main(void) {/*...*/}和 int main(int argc, char *

20165316 技能学习心得与c语言学习

20165316 技能学习心得与c语言学习 一.技能学习经验 我会打乒乓球,在中国,我只能说我"会"打,至于"比大多数人更好"我不敢断言,因为我无时无刻不感受到乒乓球圈子远比我想象的要深.但是,我觉得乒乓球学习的过程对我今后的学习有所启发,我希望通过总结给大家,最主要还是给自己,一个方向. 像乒乓球这类运动,主要是反复练习,我记忆最深刻的是小学一年级,刚刚能在台子上打球,教练就让我练习多球,即一次使用一个动作套路连续打200到300个球.之后每次练球都必须练习基本功

大一上学期C语言学习心得总结

经过一个学期的C语言学习,大体算是在这个编程语言上入了门,能够通过一些代码解决特定的问题.当然,每次成功将问题转换成代码都小有激动,虽然只是在黑框上输出了一些数字或是字符串. 编程,虽然还不是很懂,但总感觉不只是学习知识这么简单,更多给我的感受是它在潜移默化中培养了人的一种能力,用自己的话来讲就是一种”代码能力“.对于同一个问题,让大家去解开答案,可能经过一些纸笔的运算都能得出结果,但是如何把这个问题转化成代码,这就是一种能力,而仅仅是将问题转换成代码,这是较为浅层次的能力,更深层的便是通过优化

Perl语言学习笔记 9 正则表达式处理文本

1.替换 s/PATTERN/REPLACE/; #返回是否替换成功的布尔值 可以使用捕获变量,如:s/(\w)/$1/ 匹配失败则不做任何处理 2.定界符 对于没有左右之分的定界符,重复三次即可,如:s///.s### 对于有左右之分的定界符,需使用两对,一对包含模式,一对包含替换字符串,这两对可以不一样,如:s{}{}.s[]{}.s<>[] 3.可选修饰符 /g可进行全局替换,替换所有匹配到的字符串,如:s/ / /g /s:使得 . 匹配所有字符 /i:大小写无关 4.绑定操作符 $f

go语言学习(五)——面向对象编程

主要讲的是"类"和接口&和其他传统语言不一样的地方挺多的,断断续续看了好几天 下面是我的练习代码 // GoStudy0219 project main.go /* go语言学习--面向对象编程(1) go中类型的值语义和引用语义 结构体(类)的定义和初始化 */ package main import ( "fmt" ) func main() { //几种"类"的初始化 v1 := &character{"Tom&q