1972年, 贝尔实验室的丹尼斯·里奇(Dennis Ritch) 和肯·汤普逊(KenThompson) 在开发UNIX操作系统时设计了C语言。C语言是在B语言(汤普逊发明) 的基础上进行设计。
设计特性
C是一门流行的语言, 融合了计算机科学理论和实践的控制特性。 C语言的设计理念让用户能轻松地完成自顶向下的规划、 结构化编程和模块化设计。
高效性
C是高效的语言。 在设计上, 它充分利用了当前计算机的优势, 因此 C程序相对更紧凑, 而且运行速度很快。 C 语言具有通常是汇编语言
才具有的微调控制能力(汇编语言是为特殊的中央处理单元设计的一系列内部指令, 使用助记符来表示; 不同的 CPU 系列使用不同的汇编语言) , 可以根据具体情况微调程序以获得最大运行速度或最有效地使用内存。
可移植性
C是可移植的语言。 这意味着, 在一种系统中编写的 C程序稍作修改或不修改就能在其他系统运行。 如需修改, 也只需简单更改主程序头文件中的少许项即可。
强大而灵活
C语言功能强大且灵活(计算机领域经常使用这两个词)
C实现都有一个大型的库, 包含众多有用的C函数。 这些函数用于处理程序员经常需要解决的问题。
C语言的应用范围
C语言来开发文字处理程序、 电子表格、 编译器和其他产品,C 语言已成为嵌入式系统编程的流行语言。C在Linux开发中扮演着极其重要的角色
计算机能做些什么
现代的计算机由多种部件构成。 中央处理单元(CPU) 承担绝大部分的运算工作。 随机存取内存(RAM) 是存储程序和文件的工作区; 而永久内存存储设备(过去一般指机械硬盘, 现在还包括固态硬盘) 即使在关闭计算机后, 也不会丢失之前储存的程序和文件。 另外, 还有各种外围设备(如,键盘、 鼠标、 触摸屏、 监视器) 提供人与计算机之间的交互。 CPU负责处理程序
工作原理
CPU从内存中获取并执行一条指令, 然后再从内存中获取并执行下一条指令,(一个吉赫兹的CPU一秒钟能重复这样的操作大约十亿次, 因此, CPU 能以惊人的速度从事枯燥的工作) 。 CPU 有自己的小工作区——由若干个寄存器组成, 每个寄存器都可以储存一个数字。 一个寄存器储存下一条指令的内存地址, CPU 使用该地址来获取和更新下一条指令。 在获取指令后, CPU在另一个寄存器中储存该指令, 并更新第1个寄存器储存下一条指令的地址。
CPU能理解的指令有限(这些指令的集合叫作指令集) 。 而且, 这些指令相当具体, 其中的许多指令都是用于请求计算机把一个数字从一个位置移动到另一个位置。 例如, 从内存移动到寄存器。
储存在计算机中的所有内容都是数字。 计算机以数字形式储存数字和字符(如, 在文本文档中使用的字母) 。每个字符都有一个数字码。 计算机载入寄存器的指令也以数字形式储存, 指令集中的每条指令都有一个数字码。
计算机程序最终必须以数字指令码(即, 机器语言) 来表示
计算机的工作原理是: 如果希望计算机做某些事, 就必须为其提供特殊的指令列表(程序) , 确切地告诉计算机要做的事以及如何做。必须用计算机能直接明白的语言(机器语言) 创建程序。
高级计算机语言和编译器
C语言以多种方式简化了编程工作。不必用数字码表示指令; 其次, 使用的指令更贴近你如何想这个问题,使用高级编程语言, 可以在更抽象的层面表达你的想法, 不用考虑CPU在完成任务时具体需要哪些步骤。
编译器
编译器是把高级语言程序翻译成计算机能理解的机器语言指令集的程序。使用合适的编译器或编译器集, 便可把一种高级语言程序转换成供各种不同类型 CPU 使用的机器语言程序。
高级语言(如C、 Java、 Pascal) 以更抽象的方式描述行为, 不受限于特定CPU或指令集。 而且, 高级语言简单易学, 用高级语言编程比用机器语言编程容易得多。
语言标准
在1987年C语言比其他语言更依赖库, 因此需要一个标准库。 由于缺乏官方标准, UNIX实现提供的库已成为了标准库。
美国国家标准协会(ANSI) 于 1983 年组建了一个委员会(X3J11) , 开发了一套新标准, 并于1989年正式公布。 该标准(ANSI C) 定义了C语言和C标准库。
1990年国际标准化组织于采用了这套C标准(ISO C) 。
ISO C和ANSI C是完全相同的标准。 ANSI/ISO标准的最终版本通常叫作C89(因为ANSI于1989年批准该标准) 或C90(因为ISO于1990年批准该标准) 。 另外, 由于ANSI先公布C标准, 因此通常使用ANSI C。
C99标准
1994年, ANSI/ISO联合委员会(C9X委员会) 开始修订C标准, 最终发布了C99标准。在2011年发布了C11标准。
使用C语言的7个步骤
第一步定义程序的目标
要在脑中有清晰的思路,明确自己想做什么,程序需要哪些信息, 要进行哪些计算和控制, 以及程序应该要报告什么信息。
第二步设计程序
考虑如何用程序来完成它。 例如, 用户界面应该是怎样的? 如何组织程序? 目标用户是谁? 准备花多长时间来完成这个程序?还要决定在程序(还可能是辅助文件) 中如何表示数据, 以及用什么方法处理数据。
第三步编写代码
设计好程序后, 就可以编写代码来实现程序,把设计的程序翻译成 C语言。
一般使用文本编辑器创建源代码文件。 该文件中内容就是翻译的C语言代码。
第四步编译
编译器是把源代码转换成可执行代码的程序。 可执行代码是用计算机的机器语言表示的代码。 这种语言由数字码表示的指令组成。 C编译器还将源代码与C库(库中包含大量的标准函数供用户使用, 如printf()和scanf()) 的代码合并成最终的程序(更精确地说, 应该是由一个被称为链接器的程序来链接库函数, 但是在大多数系统中, 编译器运行链接器) 。 其结果是, 生成一个用户可以运行的可执行文件, 其中包含着计算机能理解的代码。
编译包含预处理,编译,汇编 链接
预处理
gcc -E 文件名.c -o 文件名.i
编译
gcc -S 文件名.i -o 文件名.s
汇编
gcc -c 文件名.s -o 文件名.o
第五步运行程序
可执行文件是可运行的程序。 在常见环境(包括Windows命令提示符模式、 UNIX终端模式和Linux终端模式) 中运行程序要输入可执行文件的文件名, 而其他环境可能要运行命令
第六步测试和调试程序
程序能运行, 但有时也可能会出现运行错误应该检查程序是否按照你所设计的思路运行。 你会发现你的程序中有一些错误,计算机行话叫作bug。 查找并修复程序错误的过程叫调试。
第七步维护和修改代码
创建完程序后, 你发现程序有错, 或者想扩展程序的用途, 这时就要修改程序。例如, 用户输入以Zz开头的姓名时程序出现错误、 你想到了一个更好的解决方案、 想添加一个更好的新特性, 或者要修改程序使其能在不同的计算机系统中运行,等。
编程机制
生成程序的具体过程因计算机环境而异。 C是可移植性语言, 因此可以在许多环境中使用, 包括UNIX、 Linux
用C语言编写程序时, 编写的内容被储存在文本文件中, 该文件被称为源代码文件(source code file) 。 大部分C系统, 包括之前提到的, 都要求文件名以.c结尾(如, wordcount.c和budget.c) 。 在文件名中, 点号(.) 前面的部分称为基本名(basename) , 点号后面的部分称为扩展名
有些UNIX系统限制整个文件名(包括扩展名) 不超过14个字符, 而有些UNIX系统则允许使用更长的文件名, 最多255个字符。
目标代码文件,可执行文件和库
C编程的基本策略是, 用程序把源代码文件转换为可执行文件(其中包含可直接运行的机器语言代码) 。 典型的C实现通过编译和链接两个步骤来完成这一过程。 编译器把源代码转换成中间代码, 链接器把中间代码和其他代码合并, 生成可执行文件。
C 使用这种的方法方便对程序进行模块化, 可以独立编译单独的模块, 稍后再用链接器合并已编译的模块。 通过这种方式, 如果只更改某个模块, 不必因此重新编译其他模块。 另外, 链接器还将你编写的程序和预编译的库代码合并。
中间文件有多种形式。即把源代码转换为机器语言代码, 并把结果放在目标代码文件(或简称目标文件)中(这里假设源代码只有一个文件)。
目标文件中包含机器语言代码,但是并不能直接运行该文件。 因为目标文件中储存的是编译器翻译的源代码, 这还不是一个完整的程序。
目标代码文件缺失启动代码(startup code) 。 启动代码充当着程序和操作系统之间的接口。
目标代码还缺少库函数。 几乎所有的C程序都要使用C标准库中的函数。 例如, concrete.c中就使用了 printf()函数。 目标代码文件并不包含该函数的代码, 它只包含了使用 printf()函数的指令printf()函数真正的代码储存在另一个被称为库的文件中。 库文件中有许多函数的目标代码。
链接器的作用是, 把编写的目标代码、 系统的标准启动代码和库代码这 3 部分合并成一个文件,即可执行文件。 对于库代码, 链接器只会把程序中要用到的库函数代码提取出来
目标文件和可执行文件都由机器语言指令组成的。 然而, 目标文件中只包含编译器为你编写的代码翻译的机器语言代码, 可执行文件中还包含编写的程序中使用的库函数和启动代码的机器代码。
UNIX系统
1.在UNIX系统上编辑
UNIX C没有自己的编辑器, 但是可以使用通用的UNIX编辑器
要输入正确的程序和为储存该程序的文件起一个合适的文件名。 文件名应该以.c结尾。
UNIX区分大小写。 因此, budget.c、 BUDGET.c和Budget.c是3个不同但都有效的C源文件名。 但是BUDGET.C是无效文件名, 因为该名称的扩展名使用了大写C而不是小写c。
以上文本就是源代码,源文件是整个编译过程的开始, 不是结束
在UNIX系统上编译
我们需要编译器将我们编写的代码(源代码) 翻译成计算机能看懂的代码(机器代码) 。 最后生成的可执行文件中包含计算机要完成任务所需的所有机器代码。使用ls命令列出文件, 会发现有一个a.out文件
该文件是包含已翻译(或已编译) 程序的可执行文件。 要运行该文件, 只需输入:a.out
如果要储存可执行文件(a.out) , 应该把它重命名。 否则, 该文件会被下一次编译程序时生成的新a.out文件替换
C 编译器会创建一个与源代码基本名相同的目标代码文件, 但是其扩展名是.o。
GNU编译器集合和LLVM项目
GNU项目始于1987年, 是一个开发大量免费UNIX软件的集合(GNU的意思是“GNU’s Not UNIX”, 即GNU不是UNIX) 。 GNU编译器集合(也被称为GCC, 其中包含GCC C编译器)
GCC的C编译器紧跟C标准的改动。 GCC有各种版本以适应不同的硬件平台和操作系统, 包括UNIX、 Linux和Windows。 用gcc命令便可调用GCC C编译器。 许多使用gcc的系统都用cc作为gcc的别名
GNU和LLVM都可以使用-v选项来显示版本信息, 因此各系统都使用cc别名来代替gcc或clang命令。
cc -v显示所使用的编译器及其版本
gcc -std=c1x inform.c
gcc -std=c11 inform.c
第1行调用C99标准, 第2行调用GCC接受C11之前的草案标准, 第3行调用GCC接受的C11标准版本。
Linux系统
Linux是一个开源、 流行、 类似于UNIX的操作系统, 可在不同平台(包括PC和Mac) 上运行。 在Linux中准备C程序与在UNIX系统中几乎一样, 不同的是要使用GNU提供的GCC公共域C编译器。 编译命令类似于:
gcc 1.3.c
在安装Linux时, 可选择是否安装GCC。 如果之前没有安装GCC, 则必须安装。 通常, 安装过程会将cc作为gcc的别名, 因此可以在命令行中使用cc来代替gcc。
PC的命令行编译器
C编译器不是标准Windows软件包的一部分, 因此需要从别处获取并安装C编译器。
源代码文件应该是文本文件, 不是字处理器文件(字处理器文件包含许多额外的信息, 如字体和格式等) 。 因此, 要使用文本编辑器(如,Windows Notepad) 来编辑源代码。
使用字处理器, 要以文本模式另存文件。 源代码文件的扩展名应该是.c。 一些字处理器会为文本文件自动添加.txt 扩展名。 如果出现这种情况, 要更改文件名, 把txt替换成c
C编译器生成的中间目标代码文件的扩展名是.obj(也可能是其他扩展名) 。 与UNIX编译器不同, 这些编译器在完成编译后通常不会删除这些中间文件。
集成开发环境(Windows)
Windows下的集成开发环境, 或称为IDE(目前, 大多数IDE都是C和C++结合的编译器)
IDE都内置了用于编写C程序的编辑器。 这类集成开发环境都提供了各种菜单(如, 命名、 保存源代码文件、 编译程序、 运行程序等) , 用户不用离开IDE就能顺利编写、 编译和运行程序。 如果编译器发现错误, 会返回编辑器中, 标出有错误的行号, 并简单描述情况。
在程序执行完毕后, 执行程序的窗口立即消失。 如果不希望出现这种情况, 可以让程序暂停, 直到按下Enter键, 窗口才消失。 要实现这种效果, 可以在程序的最后( return这行代码之前) 添加一行代码:getchar();
Windows/Linux
许多Linux发行版都可以安装在Windows系统中, 以创建双系统。 一些存储器会为Linux系统预留空间, 以便可以启动Windows或Linux。 可以在Windows系统中运行Linux程序, 或在Linux系统中运行Windows程序。 不能通过Windows系统访问Linux文件, 但是可以通过Linux系统访问Windows文档
Macintosh中的C
苹果免费提供Xcode开发系统下载它允许用户选择不同的编程语言, 包括C语言。
Xcode 凭借可处理多种编程语言的能力, 可用于多平台, 开发超大型的项目。
UNIX系统内置Mac OS X, 终端工具打开的窗口是让用户在UNIX命令行环境中运行程序。
苹果在标准软件包中不提供命令行编译器, 如果下载了 Xcode, 还可以下载可选的命令行工具, 这样就可以使用clang和gcc命令在命令行模式中编译。
特殊元素
边栏
边栏提供更深入的讨论或额外的背景, 有助于解释当前的主题。
提示
提示一般都短小精悍, 帮助读者理解一些特殊的编程情况。
警告
用于警告读者注意一些潜在的陷阱。
注意
提供一些评论, 提醒读者不要误入歧途