如何运行程序?
C 语言是一种编译型语言,也就是说计算机不会直接解释代码,而是需要将给人阅读的源代码转化(或编译)为机器能够理解的机器代码,这样计算机才能够执行。
为了编译代码,需要一个叫编译器的程序。GNU 编译器套件(GNU Compiler Collection),也叫 gcc ,是最流行的 C 编译器之一。gcc 可以在很多操作系统中使用,而且除了 C 语言,它还可以编译很多其他语言,最重要的是,它是完全免费的。
下面是用 gcc 编译并运行程序的过程:
- 将前一页那道“代码冰箱贴”练习中的代码保存在一个叫 cards.c 的文件中。
- 在命令提示符或终端中使用 gcc cards.c -o cards 命令
- 在 Windows 命令提示符中输入 cards 或在 Mac 和 Linux 终端中输入./cards 运行程序。
百宝箱
在大部分机器中,可以用下面这个技巧来编译并运行代码:
这条命令只有在编译成功的情况下才会运行新程序,一旦编译过程中出了问题,它就会跳过运行程序这一步,仅仅在屏幕上显示错误消息。
现在就应该创建 cards.c 文 件,然后编译它。随着本章内容的展开,我们会在它的基础上逐步改进。
试驾
让我们来看看程序能否成功编译和运行。在你的机器上打开命令提示符或终端,试试吧!
程序工作了!
恭喜!你已经成功编译并运行了 C 程序。gcc 编译器从 cards.c 中提取出了供人阅读的源代码,并将其转换为 cards 程序中机器才能理解的机器代码。如果你用的是 Mac 或 Linux,计算机会在一个叫 cards 的文件中创建机器代码;而在 Windows 中,所有程序的扩展名必须是.exe,因此这个文件叫 cards.exe。
这里没有蠢问题
问:为什么我在 Linux 和 Mac 中运行程序时必须在程序前加上./?
答:因为在类 Unix 操作系统中,运行程序必须指定程序所在的目录,除非程序的目录已经列在了 PATH 环境变量中。
C 语言不支持现成的字符串。
C 语言比其他大多数语言的抽象层次更低,因此它不提供字符串,而是用了相似的东西来代替:以字符为元素的数组。如果你用过其他语言,一定已经见过数组了,数组就是一张有名有姓的事物清单,所以 card_name 只是一个变量名,用来引用你在命令提示符输入的那张字符列表的。把 card_name 定义为大小为 2 个字符的数组,就可以用 card_name[0] 和 card_name[1] 分别引用第一和第二个字符。为了理解字符串的工作原理,让我们深入计算机的存储器,看看 C 语言是如何处理文本的……
字符串聚焦
字符串只是字符数组,当 C 语言看到一个这样的字符串时:
s = "Shatner"
会把它当做一个数组读取,而这个数组是由一个个独立的字符组成的:
字符串中的每个字符是数组中的一个元素,这就是为什么可以通过索引来引用字符串中的某个字符,比如 s[0] 、s[1] 。
别在字符串的尽头掉下去
当 C 语言想要读取字符串中的内容时,会发生什么呢?比如说它想打印字符串吧。在如今的很多语言中,计算机会时刻记录数组的大小,但 C 语言比大多数语言更低层,它无法确切地知道数组有多长,如果 C 语言想在屏幕上显示字符串,它就需要知道什么时候会到达字符数组的尾部,为此 C 语言加入了哨兵字符。
哨兵字符是一个出现在字符串末尾的附加字符,它的值为\0 。每当计算机需要读取字符串的内容时,它会逐一扫描字符数组中的所有元素,直到碰到\0 ,也就是说当计算机看到下面这个字符串时:
s = "Shatner"
存储器中实际保存的是:
这就是为什么我们要在代码中像这样定义 card_name 变量:char card_name[3];
字符串 card_name 只需要记录 1 到 2 个字符,但因为字符串要以哨兵字符结尾,所以我们必须把数组的大小定义为 3,以放下一个额外的字符。
这里没有蠢问题问:为什么字符要从 0 开始编号?为什么不是 1?答:字符的索引值是一个偏移量:它表示当前要引用的这个字符到数组中第一个字符之间有多少字符。问:为什么要这样做?答:计算机在存储器中以连续字节的形式保存字符,并利用索引计算出字符在存储器中的位置。如果计算机知道 c[0] 位于存储器 1 000 000 号单元,那么就可以很快地计算出 c[96] 在 1 000 000 + 96 号单元。问:为什么要设立哨兵字符?难道计算机就不知道字符串的长度吗?答:通常不知道。记录数组的长度不是 C 语言的强项,字符串其实就是个数组。问:C 语言居然不知道数组有多长?答:是的,虽然编译器有时可以通过分析代码计算出数组的长度,但一般情况下,C 语言希望你来记录数组的长度。问:单、双引号有区别吗?答:有区别,单引号通常用来表示单个字符,而双引号通常用来表示字符串。问:我应该用双引号(")定义字符串,还是以显式字符数组的形式定义字符串?答:通常应该用双引号来定义字符串。用双引号定义的字符串叫字符串字面值(string literal),比起字符数组,它输入起来也更方便。问:字符串字面值和字符数组有没有区别?答:只有一个区别:字符串字面值是常量。问:那是什么意思?答:也就是说这些字符一旦创建完毕,就不能再修改它们。问:如果我改了会怎么样?答:这取决于编译器,gcc 通常会显示总线错误(bus error)。问:总线错误?那是什么东西?答:C 语言采取不同的方式在存储器中保存字符串字面值。总线错误意味着程序无法更新那一块存储器空间。
虎口拔牙
“等号”不一定表示等于。在 C 语言中,“等号”(=)用来赋值(assignment),而“双等号”用来检查两个值是否相等。如果想要增加或减小变量的值,可以用+=和-=这两个赋值运算符,它们让代码看起来更简短。最后,如果想要对变量的值加 1 或减 1 ,可以用 + + 和--。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论