程序的基本概念

程序和编程语言

自然语言和形式语言

程序的调试

第一个程序


程序的基本概念

程序和编程语言

1.程序

程序(Program)告诉计算机应如何完成一个计算任务,这里的计算可以是数学运算,比如解方 程,也可以是符号运算,比如查找和替换文档中的某个单词。从根本上说,计算机是由数字电路组 成的运算机器,只能对数字做运算,程序之所以能做符号运算,是因为符号在计算机内部也是用数字表示的。此外,程序还可以处理声音和图像,声音和图像在计算机内部必然也是用数字表示的,这些数字经过专门的硬件设备转换成人可以听到、看到的声音和图像。

程序由一系列指令组成, 指令是指示计算机做某种运算的命令,通常包含以下几类:

  • 输入(Input):从键盘,文件或者其他设备获取数据.
  • 输出(Output):把数据显示到屏幕,或者存入一个文件,或者发送到其他设备.
  • 基本运算:执行最基本的数学运算和数据存取.
  • 测试和分支:测试某个条件,然后根据不同的测试结果执行不同的后续指令.
  • 循环:重复执行一系列操作

基本我们用过的任何一个程序,都是由这几类指令组成的,程序是虽然很复杂,但是编写程序能够用到的指令只有这简单的几种,这中间的东西需要我们来填充,所以编写程序就是一件很复杂的工作.

实质就是:把复杂的问题分解为子任务,把子任务再分解成更为简单的任务,层层分解,直到最后简单得可以用上面的指令来完成.

2.编程语言

编程语言(Programming Language)分为低级语言(Low-level Language)和高级语言(High-level Language)。机器语言(Machine Language)和汇编语言(Assembly Language)属于低级语言,直接用计算机指令编写程序。而C、C++、Java、Python等属于高级语言,用语句(Statement)编写程序,语句是计算机指令的抽象表示。举个例子,同样一个语句用C语言、汇编语言和机器语言分别表示如下:
编程语言 表示形式
C语言 a=b+1
汇编语言

mov  0x804a01c,%eax

add  $0x1,%eax

mov %eax,0x804a18

机器语言

a1 1c a0 04 08

83 c0 01

a3 18 a0 04 08

计算机中只能对数字做运算处理,符号,声音等在计算机内部都需要用数组来表示,指令也不例外,上述表中机器语言都是由十六进制数字组成的.最早一批的程序员就是使用机器语言进行编程的,但是是很麻烦的,需要查询大量的表格来确定每个数字代表的意思,编写出来的程序也不是很友好,于是再次基础上有了汇编语言,就是把机器语言中一组一组的数字用助记符表示,直接用这些助记符写出汇编程序,然后让汇编器去查表把助记符替换成数字,也就把汇编语言翻译成了机器语言.从上面的例子可以看出,汇编语言和机器语言的指令是一一对应的,汇编语言有三条指令,机器语言也有三条指令,汇编器就是做一个简单的替换工作,例如在第一条指令中,把mov ?,%eax这种格式的指令替换成机器码a1 ?,?表示一个地址,在汇编指令中是0x804a01c,转换成机器码之后是1c a0 04 08.(小端表示)

从上述例子我们还可以看出来,C语言的语句和低级语言的指令之间并不是简单都得一一对应关系,一语句a=b+1;语句要翻译成三条汇编或者机器指令,这个过程我们称为编译,由编译器来完成,显然编译器的功能比汇编器要复杂的多.用C语言编写的程序必须经过编译转成机器指令才能被计算机指令,编译需要花一些时间,这是用高级语言编译的一个缺点,然而更多的是优点.首先,用C语言编程更容易,写出来的代码更紧凑,可读性更强,出了错也更容易改正.其次,C语言是可移植的或者称为平台无关的.

首先来解释一下平台这个词的意思,可以指的是计算机体系结构,也可以指的是操作系统,也可以指开发平台(编译器,连接器等).不同的计算机体系结构有不同的指令集,可以识别的机器指令格式是不同的,直接用某种体系结构的汇编或机器指令写出来的程序只能在这种体系结构的计算机上运行,然后各种体系结构的计算机都有各自的C编译器,可以把C程序编译成各种不同体系结构的机器指令,这意味着用C语言写的程序只需要稍加修改甚至不用修改就可以在不用的计算机上编译运行.各种高级语言也都是具备C语言的这些优点,所以绝大部分程序都是用高级语言编写的,只有和硬件关系密切的少数程序(例如驱动程序)才会用到低级语言.还要注意一点,即使在相同的体系结构和操作系统下,用不同的C编译器编译同一个程序得到的结果也有可能是不同的,C语言有些语言特性在C标准种并没有明确规定,各编译器有不同的实现方式,编译出来的指令行为特性也会不同,应该尽量避免使用不可移植的语法特性.

总结一下编译执行的过程,首先你用文本编辑器写一个C程序,然后保存成一个文件,例如test.c.这称为源代码或源文件,然后运行编译器对它进行编译,编译的过程并不执行程序,而是把源代码全部翻译成机器指令,再加上一些描述信息,生成一个新的文件,例如a.out,这成为可执行文件,可执行文件可以被操作系统加载运行,计算机执行该文件中由编译器生成的指令.

有些高级语言以解释(Interpret的方式执行,解释执行过程和C语言的编译执行过程很不一样。

例如编写一个Shell脚本script.sh,内容如下:
#! /bin/sh
VAR=1
VAR=$(($VAR+1))
echo $VAR

 定义Shell变量VAR的初始值是1,然后自增1,然后打印VAR的值。用Shell程序/bin/sh解释执行这个脚本,结果如下:

$ /bin/sh script.sh
2

这里的/bin/sh称为解释器(Interpreter),它把脚本中的每一行当作一条命令解释执行,而不需要

先生成包含机器指令的可执行文件再执行。如果把脚本中的这三行当作三条命令直接敲到Shell提示符下,也能得到同样的结果:
$ VAR=1
$ VAR=$(($VAR+1))
$ echo $VAR
2

编程语言仍在发展演化。以上介绍的机器语言称为第一代语言(1GL,1st Generation Programming Language),汇编语言称为第二代语言(2GL,2nd Generation Programming Language),C、C++、Java、Python等可以称为第三代语言(3GL,3rdGenerationProgramming Language)。目前已经有了4GL(4th Generation Programming Language)和5GL(5th Generation Programming Language)的概念。3GL的编程语言虽然是用 语句编程而不直接用指令编程,但语句也分为输入、输出、基本运算、测试分支和循环等几种,和 指令有直接的对应关系。而4GL以后的编程语言更多是描述要做什么(Declarative)而不描述具体 一步一步怎么做(Imperative),具体一步一步怎么做完全由编译器或解释器决定,例如SQL语言 (SQL,Structured Query Language,结构化查询语言)就是这样的例子。

问题一:解释执行的语言相比编译执行的语言有什么优缺点?

 1.主体不同:

编译执行:由编译程序将目标代码一次性编译成目标程序,再由机器运行目标程序

解释执行:将源语言直接作为源程序输入,解释执行解释一句后就提交计算机执行一句,并不形成目标程序。

2.优势不同

编译执行:相比解释执行编译执行效率高,占用资源小,适合复杂程序
解释执行:开发速度快,出现严重BUG的几率小。

3.缺点不同

编译执行:兼容性差,例如在windows平台上写的编译程序一般不可以在unix平台上运行。

解释执行:解析需要时间,不生成目标程序而是一句一句的执行的方式会造成计算机资源的浪费,即执行效率低。

各类语言分类:

  • 编译执行:GO语言、C语言、C++
  • 解释执行:python
  • 半编译半解释型语言:java、C#

自然语言和形式语言

自然语言(Natural Language)就是人类讲的语言,比如汉语、英语和法语。这类语言不是人为设
计(虽然有人试图强加一些规则)而是自然进化的。形式语言(Formal Language)是为了特定应
用而人为设计的语言。例如数学家用的数字和运算符号、化学家用的分子式等。编程语言也是一种
形式语言,是专门设计用来表达计算过程的形式语言。
形式语言有严格的语法(Syntax)规则,例如,3+3=6是一个语法正确的数学等式,而3=+6$则不
是,H2O是一个正确的分子式,而2Zz则不是。语法规则是由符号(Token)和结构(Structure)的规则所组成的。Token的概念相当于自然语言中的单词和标点、数学式中的数和运算符、化学分子式中的元素名和数字,例如3=+6$的问题之一在于$不是一个合法的数也不是一个 事先定义好的运算符,而2Zz的问题之一在于没有一种元素的缩写是Zz。结构是指Token的排列方式,3=+6$还有一个结构上的错误,虽然加号和等号都是合法的运算符,但是不能在等号之后紧跟加号,而2Zz的另一个问题在于分子式中必须把下标写在化学元素名称之后而不是前面。关于Token的规则称为词法(Lexical)规则,而关于结构的规则称为语法(Grammar)规则.
当阅读一个自然语言的句子或者一种形式语言的语句时,你不仅要搞清楚每个词(Token)是什么
意思,而且必须搞清楚整个句子的结构是什么样的(在自然语言中你只是没有意识到,但确实这样
做了,尤其是在读外语时你肯定也意识到了)。这个分析句子结构的过程称为解析(Parse)。例
如,当你听到“The other shoe fell.”这个句子时,你理解the other shoe是主语而fell是谓语动词,一
旦解析完成,你就搞懂了句子的意思,如果知道shoe是什么东西,fall意味着什么,这句话是在什
么上下文(Context)中说的,你还能理解这个句子主要暗示的内容,这些都属于语(Semantic)的范畴。
虽然形式语言和自然语言有很多共同之处,包括Token、结构和语义,但是也有很多不一样的地
方。
现在给出一些关于阅读程序(包括其它形式语言)的建议。首先请记住形式语言远比自然语言紧
凑,所以要多花点时间来读。其次,结构很重要,从上到下从左到右读往往不是一个好办法,而应
该学会在大脑里解析:识别Token,分解结构。最后,请记住细节的影响,诸如拼写错误和标点错
误这些在自然语言中可以忽略的小毛病会把形式语言搞得面目全非。

程序的调试

编程是一件复杂的工作,因为是人做的事情,所以难免经常出错。据说有这样一个典故:早期的计
算机体积都很大,有一次一台计算机不能正常工作,工程师们找了半天原因最后发现是一只臭虫钻
进计算机中造成的。从此以后,程序中的错误被叫做臭虫(Bug),而找到这些Bug并加以纠正的
过程就叫做调试(Debug)。有时候调试是一件非常复杂的工作,要求程序员概念明确、逻辑清
晰、性格沉稳,还需要一点运气。调试的技能我们在后续的学习中慢慢培养,但首先我们要区分清
楚程序中的Bug分为哪几类。
  • 编译时错误:

    编译器只能翻译语法正确的程序,否则将导致编译失败,无法生成可执行文件。对于自然语
    言来说,一点语法错误不是很严重的问题,因为我们仍然可以读懂句子。而编译器就没那么
    宽容了,只要有哪怕一个很小的语法错误,编译器就会输出一条错误提示信息然后罢工,你
    就得不到你想要的结果。虽然大部分情况下编译器给出的错误提示信息就是你出错的代码
    行,但也有个别时候编译器给出的错误提示信息帮助不大,甚至会误导你。在开始学习编程
    的前几个星期,你可能会花大量的时间来纠正语法错误。等到有了一些经验之后,还是会犯
    这样的错误,不过会少得多,而且你能更快地发现错误原因。等到经验更丰富之后你就会觉
    得,语法错误是最简单最低级的错误,编译器的错误提示也就那么几种,即使错误提示是有
    误导的也能够立刻找出真正的错误原因是什么。相比下面两种错误,语法错误解决起来要容
    易得多
  • 运行时错误

    编译器检查不出这类错误,仍然可以生成可执行文件,但在运行时会出错而导致程序崩溃。
    对于我们接下来的几章将编写的简单程序来说,运行时错误很少见,到了后面的章节你会遇
    到越来越多的运行时错误。读者在以后的学习中要时刻注意区分编译时和运行时(Run-
    time)这两个概念,不仅在调试时需要区分这两个概念,在学习C语言的很多语法时都需要区
    分这两个概念,有些事情在编译时做,有些事情则在运行时做。

  • 逻辑错误和语义错误
    第三类错误是逻辑错误和语义错误。如果程序里有逻辑错误,编译和运行都会很顺利,看上
    去也不产生任何错误信息,但是程序没有干它该干的事情,而是干了别的事情。当然不管怎
    么样,计算机只会按你写的程序去做,问题在于你写的程序不是你真正想要的,这意味着程
    序的意思(即语义)是错的。找到逻辑错误在哪需要十分清醒的头脑,要通过观察程序的输
    出回过头来判断它到底在做什么。

第一个程序

通常一本教编程的书中第一个例子都是打印“Hello, World.”,用C语言写这个程序可以这样写:
#include <stdio.h>
/* main: generate some simple output */
int main(void)
{printf("Hello, world.\n");return 0;
}
将这个程序保存成main.c,然后编译执行
$ gcc main.c
$ ./a.out
Hello, world.

gcc是Linux平台的C编译器,编译后在当前目录下生成可执行文件a.out,直接在命令行输入这个可
执行文件的路径就可以执行它。如果不想把文件名叫a.out,可以用gcc的-o参数自己指定文件名:

虽然这只是一个很小的程序,但我们目前暂时还不具备相关的知识来完全理解这个程序,比如程序
的第一行,还有程序主体的int main(void){...return 0;}结构,这些部分我们暂时不详细解释,
读者现在只需要把它们看成是每个程序按惯例必须要写的部分(Boilerplate)。但要注意main是一
个特殊的名字,C程序总是从main里面的第一条语句开始执行的,在这个程序中是指printf这条语
句.
第3行的/* ... */结构是一个注释(Comment),其中可以写一些描述性的话,解释这段程序在
做什么。注释只是写给程序员看的,编译器会忽略从/*到*/的所有字符,所以写注释没有语法规
则,爱怎么写就怎么写,并且不管写多少都不会被编译进可执行文件中。
printf语句的作用是把消息打印到屏幕。注意语句的末尾以;号(Semicolon)结束,下一条语
句return 0;也是如此。
C语言用{}括号(Brace或Curly Brace)把语法结构分成组,在上面的程序中printf和return语句套
在main的{}括号中,表示它们属于main的定义之中。我们看到这两句相比main那一行都缩进
(Indent)了一些,在代码中可以用若干个空格(Blank)和Tab字符来缩进,缩进不是必须的,但
这样使我们更容易看出这两行是属于main的定义之中的,要写出漂亮的程序必须有整齐的缩进.
正如前面所说,编译器对于语法错误是毫不留情的,如果你的程序有一点拼写错误,例如第一行写
成了stdoi.h,在编译时会得到错误提示:
$ gcc main.c
main.c:1:19: error: stdoi.h: No such file or directory
这个错误提示非常紧凑,初学者往往不容易看明白出了什么错误,即使知道这个错误提示说的是
第1行有错误,很多初学者对照着书看好几遍也看不出自己这一行哪里有错误,因为他们对符号和
拼写不敏感(尤其是英文较差的初学者),他们还不知道这些符号是什么意思又如何能记住正确的
拼写?对于初学者来说,最想看到的错误提示其实是这样的:“在main.c程序第1行的第19列,您试
图包含一个叫做stdoi.h的文件,可惜我没有找到这个文件,但我却找到了一个叫做stdio.h的文
件,我猜这个才是您想要的,对吗?”可惜没有任何编译器会友善到这个程度,大多数时候你所得
到的错误提示并不能直接指出谁是犯人,而只是一个线索,你需要根据这个线索做一些侦探和推
理。
有些时候编译器的提示信息不是error而是warning,例如把上例中的printf("Hello, world.\n");改成printf(1);然后编译运行:
$ gcc main.c
main.c: In function ‘main’:
main.c:7: warning: passing argument 1 of ‘printf’ makes pointer from
integer without a cast
$ ./a.out
Segmentation fault
这个警告信息是说类型不匹配,但勉强还能配得上。警告信息不是致命错误,编译仍然可以继续,
如果整个编译过程只有警告信息而没有错误信息,仍然可以生成可执行文件。但是,警告信息也是
不容忽视的。出警告信息说明你的程序写得不够规范,可能有Bug,虽然能编译生成可执行文件,
但程序的运行结果往往是不正确的,例如上面的程序运行时出了一个段错误,这属于运行时错误。
各种警告信息的严重程度不同,像上面这种警告几乎一定表明程序中有Bug,而另外一些警告只表
明程序写得不够规范,一般还是能正确运行的,有些不重要的警告信息gcc默认是不提示的,但这
些警告信息也有可能表明程序中有Bug。一个好的习惯是打开gcc-Wall选项,也就是让gcc提示所
有的警告信息,不管是严重的还是不严重的,然后把这些问题从代码中全部消灭。
比如把上例中的printf("Hello, world.\n");改成printf(0);然后编译运行:

$ gcc main.c
$ ./a.out
编译既不报错也不报警告,一切正常,但是运行程序什么也不打印。如果打开-Wall选项编译就会
报警告了
$ gcc -Wall main.c
main.c: In function ‘main’:
main.c:7: warning: null argument where non-null required (argument
1)
如果printf中的0是你不小心写上去的(例如错误地使用了编辑器的查找替换功能),这个警告就
能帮助你发现错误。虽然本书的命令行为了突出重点通常省略-Wall选项,但是强烈建议你写每一
个编译命令时都加上-Wall选项。

C语言入门(一)——程序的基本概念相关推荐

  1. 都2023年了,你如果还不知道这18个C语言入门经典程序就亏了

    作为一个C语言初学者,如何学代码很重要!俗话说得好,当我刷完每一年的题,就没有我不会的题了,而C语言不需要这么麻烦,他需要记得东西其实不多,基本是哪个就是几个常见的语句加上一些关键字而已.你所看那些大 ...

  2. c语言入门小程序素数,C语言编程入门经典18个小程序

    C语言是面向过程的,而C++是面向对象的 C跟C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考量的是怎样借助一个过程,对输入(或环境条件)进行运算处理得到输出(或推动 ...

  3. 【C语言入门简单程序】三子棋——新手轻松学

    目录 设计思路 功能实现 展示棋盘 Show_board 棋盘的初始化 Initial_Board 玩家下棋 Player_Move 电脑下棋 Computer_Move 判断棋局 优化与改进 判定胜 ...

  4. c语言过程化程序设计方法,程序的设计基础(C语言入门及编程环境)(修改).ppt

    程序的设计基础(C语言入门及编程环境)(修改) 程序设计基础(一) --算法 教学目的 复习语言及程序 了解算法的概念 掌握结构化程序的三种基本结构及算法的表示方法 教学重点和难点 重点:算法的表示方 ...

  5. 一个c语言程序的开发环境,C语言入门(2)——安装VS2013开发环境并编写第一个C语言程序...

    在C语言入门系列中,我们使用Visual studio 2013 Professional作为开发工具.本篇详细介绍如何安装Visualstudio 2013 Professional并写出我们第一个 ...

  6. Java程序员Go语言入门简介

    引用:Java程序员Go语言入门简介 为什么是 Go 语言 类 C 的语法,这意味着 Java.C#.JavaScript 程序员能很快的上手 有自己的垃圾回收机制 跨平台.编译即可执行无需安装依赖环 ...

  7. 统一建模语言UML轻松入门(1)――基本概念

    统一建模语言UML轻松入门(1)――基本概念 --------------------------------------------------------------------- 宋宝华 ema ...

  8. 明解C语言入门篇_第8章_动手编写各种程序吧

    前言 本文为业余学习<明解C语言入门篇>的记录,包含代码清单和练习题. 开始学习时间:2022年8月21日 +++++++++++++++++++++++++++++++ 第1章 初识C语 ...

  9. Go 语言 入门 基于 GoLand 2023.1 创建第一个Go程序

    文章目录 Go 语言 入门 go 语言是什么? go 入门 需要 学习 什么? Go 语言有 那些优势? Go 语言 与 Java 语言 对比 Go 语言 与Python 语言 对比 Go 语言 基于 ...

  10. 明解C语言入门篇_第4章_程序的循环控制

    前言 本文为业余学习<明解C语言入门篇>的记录,包含代码清单和练习题. 开始学习时间:2022年8月21日 +++++++++++++++++++++++++++++++ 第1章 初识C语 ...

最新文章

  1. 从零开始一起学习SLAM | 为什么要用齐次坐标?
  2. 《海贼王》出品方与小冰合作:首个AI虚拟人上线日本版“微信”
  3. 关于长江的题目_长江流域综合治理练习题
  4. c语言 amp 位与 什么意思,C语言中amp;是什么意思?--龙方网络
  5. PHP 7.3 我们将迎来灵活的 heredoc 和 nowdoc 句法结构
  6. android恶意代码检测报告,用机器学习检测Android恶意代码
  7. kafka和zookeeper一键启停脚本(以及kafka关不掉问题解决)
  8. 二叉树、树和有序树的区别
  9. Consul架构介绍
  10. java中用流提取文档中的文字,语言实现从word文档中提取文本
  11. 带新手玩转MVC——不讲道理就是干(上)
  12. Syntaxhighligher 使用中的一些问题
  13. 设计分享 | STM32F103RCT6利用ULN2003驱动步进电机正反转
  14. 外卖行业现状分析_简要分析外卖运营行业的发展现状
  15. 给定经纬度计算距离_oracle 根据经纬度计算任意两地之间的距离
  16. 万洲金业:投资现货黄金的收益与风险如何平衡?
  17. opencv 矩阵行列求和
  18. PowerDesigner画ER图详细教程
  19. 源码学习之LAMMPS的一个时间步是如何工作的
  20. 单相逆变器重复控制。 采用重复控制与准比例谐振控制相结合的符合控制策略

热门文章

  1. java最好用的浏览器_国内好的pc浏览器评测
  2. JAVA生成带LOGO的二维码
  3. 一个C/C++协程库的思考与实现之协程栈的动态按需增长
  4. php frameset不显示,php加载frameset页面时显示空白怎么办_后端开发
  5. 甲乙2个人去买冬瓜,甲买差7元,乙买差9元,合买差1元,冬瓜多少钱?
  6. win7 下面串口驱动装好串口工具却找不到端口解决的方法
  7. C# Graphics类详解
  8. Web初学-2022.11.12-11.18
  9. 名片管理系统python详解_取名字大全_免费男孩女孩起名字
  10. 怎么在计算机里有桌面快捷方式,桌面快捷方式不见了,小编教你桌面软件快捷方式图标不见了怎么办...