[译] C track: compiling C programs.
原文:C track: compiling C programs.
C track: compiling C programs.
尽管有些计算机语言(如 Schema 或者 Basic)通常使用交互式的解释器(当你输入命令后,就可立即执行),但 C 语言不是。C 的源文件总是要通过一个叫做编译器(compiler)的程序编译成二进制代码然后运行。这就是我们接下来要详细说明的几个步骤。
几种不同类型的文件
你需要4种文件进行编译C 程序:
常规的源代码文件(source code)。 这些文件包含了函数定义,并约定以 "
.c" 作为结尾进行命名。头文件(Header). 这些文件包含了函数声明(也叫做函数原型)以及各种预处理语句。源文件可以通过头文件访问外部定义的函数。头文件的文件名约定以 "
.h" 作为结尾.目标文件(Object). 这些文件由编译器的输出而产生。目标文件包含了二进制形式的函数定义,本身是不可执行文件。目标文件的文件名约定以"
.o" 结尾,尽管在一些操作系统,如(Windows, MS-DOS),经常以".obj" 结尾。二进制可执行文件(Binary executables)。这些文件由一个叫做链接器(linker)的程序的输出而产生。链接器链接一些目标文件并产生可以直接执行的二进制文件。二进制可执行文件在 Unix 操作系统上没有后缀名,但在 Windows 上,通常以"
.exe" 作为后缀名。
还有其他的各种文件,尤其是静态库文件(".a" files or ".lib" on Windows)以及共享库文件(".so" files or ".dll" on Windows)。但通常,你不需要直接与他们打交道。
预处理
在编译器开始编译源文件之前,源文件由预处理器(preprocessor)进行处理。预处理器是一个真实的单独的程序(通常叫做"cpp", for "C preprocessor"),而由编译器在编译前自动调用。预处理器的工作就是讲源文件转换成另外一个源文件(你也可以认为是对源文件的修改或者扩展)。修改后的文件可能作为一个真实的文件存在文件系统中,也可能仅仅是在发送给编译器之前在内存中作短暂的保留。另外,你不需要特别关注预处理,但是你需要知道预处理是干什么滴。
预处理指令以符号("#")开始. 在多种预处理指令中,有两种最为重要:
#define. 主要用于定义常量。如,#define BIGNUM 1000000
指定在剩下的程序中任何位置处理的字符串 BIGNUM 应该被替换为 1000000。例如,这个语句:
int a = BIGNUM;
变成了
int a = 1000000;
#define语句用于避免一个常量值在源文件中多处重复出现。这在你随后需要对这常量值进行修改时是相当的重要,并且可以减少bug 的滋生,你只需要对 #define 的定义修改,而不是对常量值在整个源代码中多处的出现位置进行修改。#include. 用于访问位于源文件之外的函数定义。例如:#include <stdio.h>
在源代码编译之前,预处理器将<stdio.h> 的内容替换
#include语句所在的位置。#include总是用于主要包含函数声明和#define 语句的头文件。 这时,我们可以通过#include语句而使用一些函数,如printf和scanf, 这两个函数的声明就位于文件stdio.h 中. 在源文件中,在函数声明或者定义之前,C compilers 是不允许我们使用函数的;#include语句就是用于这种情况,从而使我们可以复用之前用C 编写的代码。
还有其他的各种预处理指令,我们将会根据需要进行有所处理。
生成目标文件: 编译器
在 C 预处理器包含了所有的头文件并且展开所有的 #define 和 #include 语句(也有其他一些在源文件中出现的预处理指令)后,编译器就可以编译程序了。编译器将 C 源文件编译成目标文件(object code),包含二进制版本源代码并以 ".o" 结尾的文件。 然而,目标文件并不能直接运行。为了能够生成可执行文件,你还需要加入被#included 包含的库函数代码(这个通过 #include 包含函数声明是不一样的)。这就是下一节要讲到的链接器 linker 的工作。
通常,编译由以下方式被调用:
% gcc -c foo.c
符号 % 是 unix 提示符. 它告诉编译器对文件 foo.c 运行预处理程序并编译成目标文件 foo.o。 -c 选项意思是由编译器将源文件编译成目标文件而不会调用链接器。如果你的整个程序就一个源文件,你也可以这么做:
% gcc foo.c -o foo
它告诉编译器在文件 foo.c 运行预处理器,编译并链接产生一个可执行文件 foo。-o 表示二进制可执行文件(程序)将以其随后的单词作为文件名。 如果你不制定 -o 选项,或者仅仅是输入 gcc foo.c,由于某种历史原因,可执行文件将以 a.out 命名。
请注意编译器的名字,我们使用的是 gcc,代表 "GNU C compiler" 或者 "GNU compiler collection" 。也有其他的编译器;他们中大多数都以 cc("C compiler")命名。在 Linux 操作系统中 cc 是 gcc 的别名。
揉成一团: 链接器
链接器的工作就是将一组目标文件(.o 文件)一起链接到一个二进制可执行文件。这包括从你的源代码文件编译的目标文件,以及预编译的库文件(library files)。 这些文件 .a 或者 .so 作为结尾命名,通常你不需要知道他们,因为他们中大多数可以由链接器(linker)定位并根据需要自动链接。
像预处理器一样,链接器也是一个叫做 ld 独立的程序。也如预处理器一样,链接器在你使用编译器时自动被调用。链接器通常使用的方式如下:
% gcc foo.o bar.o baz.o -o myprog
这一行是告诉编译器一起将三个目标文件(foo.o, bar.o, and baz.o) 链接成一个名为 myprog 的二进制可执行文件.
这就是你需要知道如何编译你的 C 程序的事情。通常,我们也推荐 -Wall 选项:
% gcc -Wall -c foo.cc
-Wall 选项让编译器对合法但是可以的代码结构发出警告,并且帮助你轻松捕获一些 bugs。如果你想要更多的编译检查项:
% gcc -Wall -Wstrict-prototypes -ansi -pedantic -c foo.cc
-Wstrict-prototypes 选项是让编译器对代码中没有正确原型的函数做出警告。-ansi 和 -pedantic 是让编译器对代码中不可移植的结构(e.g. 一些在 gcc 中合法而不满足标准 C compilers 的代码结构;这些结构通常是需要避免的)做出警告。
References
Kernighan and Ritchie, The C Programming Language, 2nd Ed.
The man page for
gcc. Type:man gccat the unix prompt.The GNU Info documentation on
gcc. Warning! This is far more information than most people could possibly absorb in the average millenium.Info documentation on
gcccan be accessed through the GNU emacs editor by typing "M-x info" (where "M-x" means to hit the meta-key and "x" simultaneously), or "C-h i" (where "C-h" means to hit the control key and "i" simultaneously), followed by "mgcc<return>". Type "minfo<return>" instead for a quick tour of how to use info. You can also access the info documentation from the unix command line by typinginfo gcc.
[译] C track: compiling C programs.的更多相关文章
- Linux内核Makefile文件(翻译自内核手册)
--译自Linux3.9.5 Kernel Makefiles(内核目录documention/kbuild/makefiles.txt) kbuild(kernel build) 内核编译器 Thi ...
- Beginning Scala study note(1) Geting Started with Scala
1. Scala is a contraction of "scalable" and "language". It's a fusion of objecte ...
- linux内核的makefile.txt讲解
linux内核的linux-3.6.5\Documentation\kbuild\makefiles.txt Linux Kernel Makefiles This document describe ...
- CUDA1-hello world
电脑配置:windows7 sp1 64bit + CUDA6.5 + GeForce GTX780 Ti 显卡中的GPU因为多核可以处理很多相同的操作,相比较来说cpu就像个健全的手,什么活都能干 ...
- 安装coreseek找不到mysql
1.安装 coreseek-3.2.14 遇到问题:“ERROR: cannot find MySQL include files,随即在网上搜索各种答案说是要找到mysql.h的正确路径加入./co ...
- OpenMP for Fortran
OpenMP for Fortran OpenMP Directive Syntax of OpenMP compiler directive for Fortran: !$OMP Directive ...
- mysql 升级方法
Performing an In-place Upgrade This section describes how to perform an in-place upgrade. Review Bef ...
- 《 UNIX网络编程》源码的使用
学习编程这东西,看代码,改代码,运行代码这样才能学到实际东西!本书说在www.unpbook.com可以获取源码,不过打不开!所以google unpv13e.tar.gz 并在网络上找到了:源码:h ...
- 嵌入式Linux-GNU Make 使用手册(中译版)
GNU Make 使用手册(中译版) 翻译:于凤昌 译者注:本人在阅读Linux源代码过程中发现如果要全面了解Linux的结构.理解Linux的编程总体设计及思想必须首先全部读通Linux源代码中各级 ...
随机推荐
- 百度地图刷新显示不完整?(应该是和div顺序有关系)
解决方案:1异步加载(jquery(function(){loadJScript():})) 2解析加载设置了个延迟(setTimeOut(getInit,1000))
- 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationContext, CoreDispatcher, ThreadLocal, ThreadStaticAttribute
[源码下载] 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationCont ...
- 重新想象 Windows 8 Store Apps (49) - 输入: 获取输入设备信息, 虚拟键盘, Tab 导航, Pointer, Tap, Drag, Drop
[源码下载] 重新想象 Windows 8 Store Apps (49) - 输入: 获取输入设备信息, 虚拟键盘, Tab 导航, Pointer, Tap, Drag, Drop 作者:weba ...
- Webhooks PHP
Webhooks/Parse When webhooks are triggered in the gateway, a notification is sent as a POST request ...
- java中的代码块执行顺序
/* 代码块:在Java中,使用{}括起来的代码被称为代码块. 根据其位置和声明的不同,可以分为 局部代码块:局部位置,用于限定变量的生命周期. 构造代码块:在类中的成员位置,用{}括起来的代码.每次 ...
- mvc设计模式和mvc框架的区别
Spring中的新名称也太多了吧!IOC/DI/MVC/AOP/DAO/ORM... 对于刚刚接触spring的我来说确实晕了头!可是一但你完全掌握了一个概念,那么它就会死心塌地的为你服务了.这可比女 ...
- Angularjs,WebAPI 搭建一个简易权限管理系统 —— 系统业务与实现(三)
目录 前言 Angularjs名词与概念 Angularjs 基本功能演示 系统业务与实现 WebAPI项目主体结构 Angularjs 前端主体结构 系统业务与实现(二) 上一章我们讲解的 Angu ...
- ASP.NET Web API 通过Authentication特性来实现身份认证
using System; using System.Collections.Generic; using System.Net.Http.Headers; using System.Security ...
- Angular 核心概念
module(模块) 作用 通过模块对页面进行业务上的划分,根据不同的功能划分不同的模块. 将重复使用的指令或者过滤器之类的代码做成模块,方便复用 注意必须指定第二个参数,否则变成找到已经定义的模块 ...
- 公司outing选项
Sign up: 2014 Summer Outing 请您从以下三个方案中选择您最感兴趣的一个项目, 如果您不能参加此次summer outing, 请选择"遗憾放弃"- ...