第一章--C语言的基本概念
丹尼斯 里奇
一、什么是C语言?
定义:是一个面向过程的计算机高级语言--不需要任何运行环境便能运行的程序语言;
发展:目前是C11 ( K&R C—>ANSI C / C89标准—>C99标准——>C11标准);
二、什么是C程序?
概念:有很多的函数(小程序段)构成,main函数为主函数-程序执行入口;
C语言执行过程:程序编写出来通过(编译器)编译连接后生成机器语言,计算机才可以执行。目前用的Clang编译器是作者: 克里斯·拉特纳(英语:Chris Lattner,1978年)
第二章--基本语法
(关键字、标识符、数据、注释、常量、变量、printf/scanf、函数、进制)
一、什么是关键字?
概念:C语言本身提供的具有特殊功能的字符 (共32个);
注意:全都是小写字母,系统会自动高亮;
1-----------------------数据类型关键字
- int :整型数据,通常为默认类型;
- float :单精度浮点型;
- double :双精度浮点型;
- char :字符型类型数据,属于整型数据的一种;
- void :空类型,声明函数无返回值或无参数,声明无类型指针,显式丢弃运算结果 ;
- short :修饰int,短整型数据,可省略被修饰的int;
- long :修饰int,长整形数据,可省略被修饰的int;
- signed :修饰整型数据,有符号数据类型;
- unsigned :修饰整型数据,无符号数据类型;
- struct :结构体声明;
- union :共用体声明;
- enum :枚举声明;
- typedef :声明类型别名;
- sizeof :得到特定类型或特定类型变量的大小;
- auto :指定为自动变量,由编译器自动分配及释放。通常在栈上分配
- static :指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部
- register :指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数
- extern :指定对应变量为外部变量,即标示变量或者函数的定义在别的文件中,示编译器遇到此变量和函数时在其他模块中寻找其定义。
- const :与volatile合称“cv特性”,指定变量不可被当前线程/进程改变(但有可能被系统或其他线程/进程改变)
- volatile :与const合称“cv特性”,指定变量的值有可能会被系统或其他进程/线程改变, 强制编译器每次从内存中取得该变量的值
2-----------------------流程控制关键字
- return :用在函数体中,返回特定值(或者是void值,即不返回值)
- continue :结束当前循环,开始下一轮循环
- break :跳出当前循环或switch结构
- goto :无条件跳转语句
- if :条件语句,后面不需要放分号
- else :条件语句否定分支(与if连用)
- switch :开关语句(多重分支语句)
- case :开关语句中的分支标记
- default :开关语句中的“其他”分支,可选。
- for:循环结构,for(1;2;3)4;的执行顺序为1->2->4->3->2...循环,其中2为循环条件;
- do :do循环结构,do 1 while(2); 的执行顺序是1->2->1...循环,2为循环条件;
- while :while循环结构,while(1) 2; 的执行顺序是1->2->1...循环,1为循环条件;
二、什么是标示符?
概念:在程序中自定义的一些符号和名称;由26个英文字母的大小写、10个阿拉伯数字0~9、下划线_,$组成;
注意:
- 1.不能以数字开头
- 2不能与关键字重名
- 3.严格区分大小写
- 4.起名要有意义
- 5.便于识别(驼峰命名)
三、什么是数据?
概念:在计算机中的存储形式,由二进制数0和1组成。例如文字、图片、声音;
注意:
- 单位:1byte(字节)=8bit 1KB=1024byte 1MB(兆)=1024KB 1G=1024MB 1T=1024G;(最小单位为bit)
- 分为静态数据和动态数据;
- 静态数据:硬盘中存储的内容,长期有效存在;
- 动态数据:系统缓存当中的内容,一旦停电则会消失;
MB与Mb的区别:一般数据机及网络通讯的传输速率都是以「bps」为单位。
大写 B代表 Byte,小写 b 代表 bit。如4Mbps 及 10Mbps 等等。以1M 宽带为例,1Mbps 等如1 X 1024/8,亦即等如128 KB/s
10M 光纤下载速度=1秒钟可以下载1.28MB(兆)的数据.---理论上
三(1)什么是数据的数据类型?
概念:有五大数据类型。基本类型、构造类型、指针类型、空类型、定义类型;


注意:
- 1整型:用于表示整数,根据表示范围的不同分为以下三种: 短整型(short) < 整型(int) < 长整型(long);
- 2浮点型:用于表示小数,根据范围和精度不同分为以下两种: 单精度浮点数(float) 精度为7位< 双精度浮点数(double) 精度为16位;
- 3字符型:用来述单个字符,char ;
四、什么是注释?
概念:对代码进行解释说明,辅助调试代码,不参加编译
- 单行注释://想注释的内容
- 多行注释:/*想注释的内容*/
注意:
- 只能在一句完整的代码后面.不能在前面,或插在中间;
- 多行注释可以嵌套单行,但是不能嵌套多行;
五、什么是常量?
概念:一些固定不变的量;
注意:数据不会改变!!
- 二进制数: 0b开头 0b00001010;
- 八进制数: 0开头 012;
- 十进制数: 默认 10
- 十六进制: 0x 0xff01
- 单精度:2.3f
- 双精度:4.5 (默认)
- 例如:'a' ,' ', '$', '\n' (转义字符)
- 例如:"abc", "a", " "(空格), ""(空字符串)
五、什么是变量?
概念:表示一个需要经常改变或者不确定的数据,(变量在内存中代表了一块内存区域);
使用流程:定义——>初始化——>使用
int a;
int a,b,c;
变量定义后不赋值:这个变量的值是不确定的(1.随机数 2.上个程序在内存中驻留的3.系统的)
2.变量的初始化
- 1)先定义,后初始化
- 2)定义的的同时初始化
- 3)使用其他的变量初始化
- 4)连续初始化
int a,b,c;
a = b = c =10;
- 1.作用域是其所在位置之下的所有函数,都可以共享并改变.
- 2.变量的使用遵循就近原则如果函数内有同名变量,那么用函数自已的.
- 3.如果没有初始化赋值,默认值是0;
- 创建一个变量相当于在内存中占用了一块空间
- 这个空间的大小是固定的,但里面的数据可以改变
- 同一个作用域内不能有相同的变量名.
- 块的内部可以访问全局变量
- 在块的外部不能访问块内部的局部变量
- 块的内部可以定义和全局变量同名的变量(互不干扰)
- 初始化时创建,在函数作用域执行完后失效,且内存空间释放.
六、什么是printf函数?
概念:标准的输出函数
输出的原理 : printf把要输出的内容--->输出缓冲区-->输出到控制台
格式:printf("格式说明",变量列表)
常见的格式说明符:
%d 整型
%c 字符型
%s 字符串型
%f 浮点型
%p 地址
用法:
int a=10;
printf("hello world----%d",a);
七、什么是scanf函数?
概念:C语言中标准的输入函数 接收用户从键盘上输入的内容(阻塞式函数-等待用户的输入,如果不输入会一直等待)
格式:scanf("格式控制",地址列表)
---地址怎么来的? ---&-取地址符号
用法:接受数字(单个/多个/数字字符混合型)
int a;
scanf("%d",&a);
八、什么是函数?
概念:组成C语言源程序的基本单位,完成特定功能的代码段.
main()为主函数:程序入口
优点:对一个功能进行封装,提高程序可读性、复用性,提高开发效率;
定义:
返回值类型 函数名(形式参数类型 参数名1,……){
函数体;
//return (返回值)
}
函数定义到使用分三步:1、声明--->2、定义函数--->3、调用函数。
一共四种类型:
- 有参无返回值:void test(int x,float y){ }
- 无参无返回值:void test1(){ }
- 有参有返回值: int max(int x,int y){ return x>y?x:y; }
- 无参有返回值: int test2(){ return 10;}
1.函数的参数
1)形参和实参
形参:在定义函数的时候,函数名后面小括号中的参数 , 格式: 数据类型 变量 如:int x;
形参的作用域:只能在本函数中使用
实参:调用函数的时候传递的参数
max(56,78);
56、78就是两个实际参数
2)参数的传递的过程
2、函数的返回值
概念:执行函数体中的程序段,最后获取的值并返回给主调函数,函数的返回值只能通过return 关键字进行返回
格式:return 表达式;/ return (表达式);
注意:
-
return 0; return (a+b); return a>b?a:b;
-
返回值类型不定义默认是int.如果不需要具体返回值类型用void(return可以省略);
- 返回值类型要与返回值相同;
-
是否要定义形参看是否有未知内容参与运算,调用时实参必须对应.参数传递的是值.;
-
函数中可以有多个return ,但是只有一个起作用;
3、函数的调用
1)函数的声明:
由于程序是由上到下执行,编译器不知道我们是否已经定义了某个函数,为了防止编译器编译的时候报错(函数调用)所以,要告诉编译器,我已经定义了哪些函数
- 原则:
在调用函数之前,进行该函数的声明
- 声明的方法:
技巧:复制函数的头部,加上分号,写在调用调用方法之前
int max(int x,int y); //声明
max(56,78); //调用
2)函数的调用
定义:函数名(实参列表);
注意:
1)形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。
2)实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值 。
3)实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配的错误。
4、递归函数
概念:在函数中自己调用函数自己
- 能够进行递归的有两个条件:
1)能够找到让问题的规模缩小的规律
2)能够让递归结束的条件
- 递归函数的执行有两个阶段:
1)递推阶段:问题规模缩小的过程
2)回归迭代:迭代计算值得过程递归的
优点和缺点:
- 优点是:遇到问题规模能够缩小,而且有规律的问题的时候,代码比较简洁
- 缺点:消耗内存
- 建议:在程序中不能用太多
进制及内存分析
二进制:0b或者0B开头 ----逢二进一 0101
八进制:0开头 ----逢八进一 01234567
十进制:直接写 ----逢十进一 0123456789
十六进制:0x或0X开头 ----逢十进一 0-9 A B C D E F (内存的地址格式)
进制的打印输出:
%o:表示输出不带符号八进制整数
%x:表示输出不带符号十六进制整数
%d:表示输出有符号十进制整数
%u:表示输出不带符号十进制整数
注意:
- 二进制不可以直接输出.
- 有符号与无符号区别:有符号可以有负数表现(如: - 2)
进制互换
三个要素:
数位(0-7)、
基数(每一位能取值的个数)、
位权(数码*基数^数位)、 101 = 1*2^0+0*2^1+1*2^2
数码(每一位是1还是0)
转换:有得时候转换为人能识别的数制,要操作计算机写计算机能够识别的语言(二进制)
10 -> 2 : 除2取余法,把10进制数除以2,然后取得余数的序列,再倒序
2 -> 10 : 所有位的位权相加 101 = 1*2^0+0*2^1+1*2^2
2 --> 16 : 4合1法, 整数部分从右向左 4位结合成一位,小数部分从左向右4位结合1位, 不足部分补0
16 -->2: 1拆4法, 16进制的1位拆成二进制的4位
2-->8 8-->2:3合1 :1拆3
8 --> 10 : 8--> 2 --> 10
16 --> 10: 16 -->2 -->10
3、原码、反码和补码
1)机器码、真值
一个数的二进制的表示 机器码
把一个数的二进制转换为10进值得值 真值
2)计算数据的存储
存储的时数的补码 数是有正负性
正数:最高位 用0表示符号位
负数:最高位 用1表示符号位
3)原码、反码、补码:
正数:就是其二进制表示 +100000001
负数:二进制的最高位是1 -1 11111110
反码:
正数:就是其二进制表示 +100000001
负数:符号位不变,其他位逐位取反 -1 11111110
补码:
正数:就是其二进制表示 +1 00000001
负数:反码+1 -1 11111111
注意:补码的真值不等于原码的真值的
4、为什么要使用补码?
主要是位了优化计算机中的减法
5、补码的深入讲解
1-1 = 1+(-1)
数据取值范围
一.基本数据类型取值范围---超出取值范围数据会定义失败.
内存管理
内存分为5大区域
栈区 -- 存放局部变量
堆区 -- 程序运行过程中,动态分配的内存
BSS区 -- 未初始化的全局变量和静态变量
数据段 -- 已经初始化的全局变量和静态变量
代码段 -- 程序编译产生的二进制的数据
4、动态内存管理
1) malloc
(void *)malloc(size) //动态的向内存申请连续的size个字节
返回的是新申请的内存空间的首地址
int *p = (int *)malloc(100); //p是在栈区 malloc(100) 在堆区
malloc不会把新申请的空间初始化
memset(p,0,100); //全部初始化为0
2) calloc
calloc 可以向堆区连续申请多个少
长度为指定长度的空间
int *p = (int *)calloc(5,4); //申请5个长度为4的空间 calloc可以把新申请的空间初始化0
注意:判断一个空间是否申请成功
if(p!=NULL){
//只有申请成功了,才能操作
}
3) realloc
重新改变一块内存空间的大小 p = (int *)realloc(p,size);
4) free
释放我们指定的内存空间
free(p); //p是我们新申请的内存单元 free后,p是一个野指针
如果不释放,造成内存的泄露
位运算
一,是什么?
是直接对整数在内存中的二进制位进行操作的方法(只能操作整形数据)
二,有什么用?
直接通过操作二进制的位来实现运算,高效
三,怎么用?
&与运算:对应两个二进位均为1时,结果位才为1,否则为0。(有假为假==0)
|或运算:对应的两个二进位有一个为1时,结果位就为1,否则为0。(有真为真==1)
^ 异或运算:对应的二进位不同时为1,否则为0。(不同为真==1,相同为假==0)
注意:1.相同整数相^的结果是0.2.一个数^另一数两次结果不变3.整数相^跟顺序无关
~ 取反运算:对整数的各二进位进行取反,包括符号位(0变1,1变0,真假互换)
<< 左移:把整数的各二进位全部左移n位,高位丢弃(包括符号位),低位补0。
左移n位其实就是乘以2的n次方(但移动后符号位变化除外,符号位改变则正负改变)
>> 右移:把整数的各二进位全部右移n位,符号位不变。高位的空缺是正数补0;
是负数高位是补0或是补1 取决于编译系统的规定;右移n位其实就是除以2的n次方