Day1-C语言概述

计算机与程序

从计算机运行原理的角度分析,计算机其实是非常不“智能”的,因为计算机所有要执行的动作,都要通过程序进行指定,没有了程序,计算机就是一堆电子元件的组合而已,即使通上电也不能执行什么操作。所以,计算机的智能,反映的其实是编程人员的智慧。

程序设计语言的发展

程序设计语言发展到现在,大致经历了三个阶段,分别是机器代码、汇编语言和高级语言三个阶段。计算机发展的初期,人们都是直接基于CPU的指令集编写二进制的机器代码,编写这种代码工作量巨大 ,不易发现和调试程序的错误,加之在一款CPU上编写的代码不能移植到另一款CPU上,所以开发效率不高。后来,人们通过使用一些具有具体意义的符号来代替CPU的指令,比如ADD表示加法指令,JPM表示跳转指令,以此发明了汇编语言。以下是一段Intel 8086 CPU的汇编程序。

start: mov ax,data  
  mov ds,ax
  lea dx,infon
  mov ah,9
  int 21h
  lea dx,buf
  mov ah,10
  int 21h
  mov cl, [buf+1]
  mov ch,0
  lea di,buf+2
  call datacate
  call ifyears
  jc a1
  lea dx,n
  mov ah,9
  int 21h
  jmp exit
a1:    lea dx,y
  mov ah,9
  int 21h
exit:  mov ah,4ch
  int 21h

汇编语言使得人们终于可以直接看懂指令的意义以及整个程序大致完成的工作。但是计算机已经不能识别汇编语言了,因为计算机只能识别由0和1组成的二进制代码。所以汇编语言需要一个叫做*汇编程序*的软件进行翻译,将具体的符号翻译成机器代码,计算机才可以识别。
从机器代码到汇编语言是编程语言的一大进步,汇编语言已经在朝着人的自然语言靠近了,但是汇编语言仍然具有代码逻辑复杂,无法结构化编程,与硬件高度相关,代码无法进行移植的特点,所以汇编语言仍是一种低级语言。
为了克服低级语言的缺点,人们开始创造各种高级语言,高级语言与人的自然语言更加靠近,它很接近人们使用自然语言的习惯,所以使用高级语言写出的程序很容易理解。而且,高级语言对程序的设计进行了高度的抽象与凝练,使得语言可以不依赖于具体的机器型号,程序开始很方便地可以在各种型号的计算机上进行移植。C、C++、JAVA、Python都是高级语言的代表。当然,随着计算机编程语言的发展,C已经被归类到中级语言的行列了。

C语言

C语言诞生于20世纪70年代。1972-1973年间,美国贝尔实验室的D.M.Ritchie在B语言的基础上设计了C语言。C语言设计之初的目的是为了描述与实现当时著名的UNIX操作系统。1973年,Ken Thompson和D.M.Ritchie用C语言重写了90%以上的UNIX系统,随着UNIX系统的广泛使用,C语言也迅速得到推广。
Alt text

C语言特点

C语言是一种非常优秀的语言,在那个连操作系统都是用汇编语言编写的年代时,C语言的出现可谓是具有划时代的意义。总结起来,C语言有以下几个特点:
1、C语言是一种结构化的程序设计语言。结构化意味着在设计程序的时候,可以将程序分成不同的模块,分模块编写代码,最后将各个模块“组装”起来完成程序的设计,采用这种方式将程序细化到了人脑可以处理的难度,大大降低了程序设计与调试的难度。
2、C语言既有高级语言那样贴近人自然语言的特点,又不失低级语言的功能。使用C语言可以直接操作计算机的内存和CPU的各种寄存器,这使得使用C语言编生成的目标代码质量高,具有非常高的执行效率。
3、C语言存在规范的标准,使用同一标准写出的C语言代码可以无障碍地在各套CPU架构下进行移植,可移植性好也是C语言强大的体现。
基于以上种种特点,C语言又具有“王者”或“母语”之称,许多著名的系统软件都是用C语言编写的。
Alt text

数学基础

所有的科学归根结底都是数学,编程尤其如此,深厚的数学功底在编程中是非常有用的。但由于课程的时间限制,我们没有那么多的时间去深入地学习数学,以下只介绍几个最基本的数学知识,以后的学习过程中,希望同学们能有意识地加强自己的数学水平。

二进制与数制转换

C语言中常用的进制是10进制,2进制,8进制,16进制,以下是它们的转换关系。(C语言中没有直接用2进制表示的数据,但有可以用8进制和16进制进行表示的数据。八进制以数字0开头,十六进制以0x或0X开头,16进制符号A~F不区分大小写。)

转成十进制

二进制:
101 = 1_2^2 + 0_2^1 + 1_2^0
101.1 = 1_2^2 + 0_2^1 + 1_2^0 + 1_2^(-1)
八进制:
074 = 7_8^1 + 4_8^0
十六进制:
0X3FE = 3_16^2 + 15_16^1 + 14_16^0

十进制转二进制

十进制整数转二进制:除二求余,逆序排列。
十进制小整数进制转二进制:乘二取整,顺序排列。
Alt text

二进制与十六进制快速转换

111010101010101101
11,1010,1010,1010,1101
6,10,10,10,13
6,A,A,A,D
0x6AAAD
111010101010101101 = 0x6AAAD

数据范围

根据排列组合的知识,x个具有n种状态的元素,它们的组合一共有x的n次方种状态。根据这点,可以用来计算二进制的数据范围,比如,8个二进制位,由于每个二进制位只具有0和1两种状态,所以8个二进制位可以表示2的8次方共256种状态,从00000000到11111111,转换成十进制是0到255,所以8位二进制可以表示的数据范围是0到255。

计算机存储单位转换

单位

容量

bit

位,用于存储一个二进制位

Byte

字节,8bit等于一个Byte

KB

2^10个Byte

MB

2^10个KB

GB

2^10个MB

TB

2^10个GB

第一个C语言程序

#include 
int main() 
{
 printf("hello, huiwen\n");
}

编译:gcc hello.c –o hello
执行:./hello

第二个C语言程序

#include 
int main() 
{
 int i = 1;
 int j = 2;
 int sum = i + j;
 printf("sum is %d\n", sum);
}

内存图

Alt text

取地址与解地址

#include 
int main()
{
    int i = 1;
    int j = 2;
    int sum = i + j;
 printf("sum is %d\n", sum);
    printf("i address is %p\n", &(*(&i)));
    printf("j address is %p\n", &j);
    printf("sum address is %p\n", &sum);
    printf("i is %d\n",  *(&i) );
    printf("j is %d\n",  *(&j) );
    printf("sum is %d\n", *(&sum) );
}

五则运算

#include 
int main()
{
    int i = 20;
    int j = 3;
    printf("%d\n", i + j);
    printf("%d\n", i - j);
    printf("%d\n", i * j);
    printf("%d\n", i / j);//整除
    printf("%d\n", i % j);//取模
}

注释

注释是程序中的说明语句,用于解释某些语句的作用,其目的是为了方便阅读程序。注释不参与C语言的编译,任何注释都会在编译过程中都会被忽略。

注释形式

单行注释: //注释内容
多行注释: /注释内容/

注释规范

  1. 每个C文件开头都一段注释,标明文件的名称,作者,编写日期,文件描述与版本修改,下面是一个可以参考的例子:
/*=====================================================
*   Copyright (C) 2014 All rights reserved.
*   
*   Filename:calculate.c
*   Author:luqiang
*   Date:2015/01/12
*   Description:this is the description.
*
======================================================*/
  1. 每个函数的定义处都需要写注释,表示该函数的名称,作者,作用,以及该函数的输入输出值。
  2. 程序的关键代码需要用注释说明
  3. 注意注释不要过多,很多时候,可以通过合理的命名让程序具有*自解释性*。

关键字

关健字又称保留字,是预留给C语言本身使用的名词,在C语言中不可以用作其他用途,比如,不可以用关键字给变量命名,C89规定的关键字共有32个。根据关键字的作用分为四类:

  1. 数据类型关键字(12个)
  2. int, char, short, long, float, double, signed, struct, unsigned, union, enum,void
  3. 控制语句关键字(12个)
  4. break, case, continue, default, do, else, for, goto, if, return, switch, while
  5. 存储类型关键字(4个)
  6. auto, extern, register, static
  7. 其他关键字(4个)
  8. const, sizeof, typedef, volatile

数据类型

基本数据类型:int char float double
结合数据类型:数组[],指针*
构造数据类型:结构体,联合体,枚举类型
空类型:void

变量

变量代表一段有名字的内存空间,定义变量的方式是 数据类型 + 名称,比如int i 定义了一个整型变量。

标识符

用来表示程序中使用的变量名、数组名、函数名和其它由用户自定义的数据类型的名称。定义标识符的时候要注意以下几点:

  1. 只能由英文字母、数字和下划线构成,长度为1~32;
  2. 必须以字母或下划线“_”开头;
  3. 标识符严格区分大小写字母;
  4. 不能以C语言的关键字作为标识符;
  5. 标识符选用应尽量做到“见名知意”,即选用有含义的英文单词或缩写,如sum, name, max等。

运算符、操作数、表达式

运算符是可以对数据进行运算的符号,比如sizeof以及+ - * / %等符号。
运算符操作的对象称为操作数,运算符与操作数组合成表达式。表达式结尾没有分号,如果在表达式两边加上一个括号,那么表达式最终可以得到一个值,这是表达式与语句的区别。

程序错误分类

编译时错误

Error

程序中有语法错误,编译不通过,不能生成可执行文件。

Warning

程序中存在潜在的错误(比如printf未提供与占位符个数相等的参数),编译可以通过,可以生成执行文件。有些警告需要加-Wall选项才会提示Warning。

运行时错误

符合C语言语法规则,但是程序的逻辑设计与目的不符,比如程序要完成求乘法功能,写程序的时候写成了求加法。

  • 无标签