c primer plus 学习笔记
第一章 认识C语言
第二章 C语言概述
C语言的基本模块:
- 函数
- 形参:变量
- 实参:值
C语言重要特性
- 转义序列escape sequence
- 占位符
C语言的结构
程序(由多个函数组成)
头文件
#include<stdio.h>
包含一个文件,C编译器的预处理指令#(头文件可定义一些常量,函数名,实际代码在另一个库文件中,头文件相当于组织程序)
/*注释*/
//注释
分号结尾;
函数
函数头
int main(void)
int返回类型,main是主函数,void表示空参数- 返回类型
- 函数名
- 形式参数
函数体
声明
int num;
变量(variable)标识符(identifer)声明(declaration) ->mem位置,数据类型关键字
变量名:
- C99/C11变量标识符最长63个字符,外部标识符最长31个字符
- 大小写字母,数字,_,不能以数字开头
- 所有变量必须先声明才能使用
语句
- 跳转语句
- 赋值表达式(存储值到内存空间)
- return语句 返回值
- 跳转语句
第三章 数据和C
数据 承载信息的数字和符号
- 常量constant
- 程序运行过程中不改变;
- 编译器根据书写形态自动判断数据类型
- 变量variable
- 可变或被赋值
- 声明时需要指定类型
基本类型关键字:
数据类型按存储方式分两大数据类型: 浮点数范围>整数
整数类型
没有小数位的数
graph TB char(char: '4', 'ABC')-->encode(encode:ASCII,EBCDIC,CJK字符集,Unicode,UTF-8...) encode-->int int-->进制(进制:16,8,2..) 进制-->bit
int
char
_Bool
1 bit. 1为true,0为false
浮点数类型
类似实数
分两部分存储 7.0=0.7E1- 指数部分1
- 小数部分0.7
- 任何区间实数无穷多,计算机无法存储所有值,只存储近似值,会损失精度
字节byte=8bit
字:计算机寻址单位
整数类型 | 占位长度 |
---|---|
short | 16bit |
int | 16bit/32bit |
long | 32bit |
long long | 64bit |
程序中超出最大值会重新开始计算,类似汽车里程表
C语言数据类型(分配合适内存空间)
scanf(“%f”, &indentifer)将输入的值赋值给标识符indentifer
& 找到指定变量标识符的地址
printf中转换说明决定了数据的显示方式,而不是存储方式.
char
- 字符常量:使用‘ ’引起来表示字符,编译器会识别并根据编码转换成整数值;
也可以直接把编码赋值给变量标记符
- 不带引号是变量标识符
- “ ”表示字符串
- 转义序列
第四章 字符串和格式化输入/输出(数据表示)
数组array存储字符串,占用连续的字节空间.
4.2字符串(字符序列)(双引号)
存储:
char
类型的array
中
数组:
1 | char id[40] //40字节空间的char类型array |
sizeof():以字节为单位给出对象大小
strlen():计算字符串的字符长度
4.3常量和C预处理器
符号常量symbolic constant(编译时替换compile-time subsitution=明示常量manifest constant)
1 |
const限定符,表示变量为只读
1 | const int NAME = value; //NAME不可更改, 用起来比define灵活 |
printf()/scanf() I/O函数
使用转换说明符(conversion specification)转换成可显示的形式.
第五章 运算符,表达式expression和语句statement(数据处理)
数据处理:
- 算术运算
- 数值比较
- 修改变量
- 逻辑组合关系
大多语句由表达式构成;表达式可能包含子表达式;
一条语句是一条完整的计算机指令.带(;)号
循环
1 | while(condition){ |
基本运算符
赋值运算符=
使用赋值的思想才能解释 i = i + 1
- 对象定位值(可修改的左值)variable = value
- 目的:把值(数据对象)存储到内存位置上
加法运算符+
- 二元运算符
需要两个运算对象
- 一元运算符
正号+
减法运算符-
- 二元运算符`需要两个运算对象
- 一元运算符
负号-
乘法运算符*
除法运算符/
截断:整数除法的小数位被丢弃
C99使用趋零截断,-3.8转换成-3
运算符优先级
其它运算符
sizeof(type/variable) 返回size_t(无符号整数类型)类型的值
1 | typedef double real; //typedef 为double创建别名real |
求模运算符 % 常用于根据求模结果是否为0控制流程
负数使用趋零截断,以每个对象的符号为正负取结果为正负
递增运算符++/递减运算符 - -
前后辍只有自身没有运算符或赋值运算符时结果都是一样的,但复合运算时会影响结果.
前辍模式:
1
a_post = 2 * a++ // a_post = 2a, a = a + 1
后辍模式:
1
pre_b = 2 * ++b // b = b + 1, pre_b = 2b
第六章 C控制语句:循环,嵌套循环
程序流:
- 语句序列
- 循环
- 分支
三种循环:(入口循环:for/while;出口循环:do while)
for
1
2
3for(initialize;test;update){ //使用分号分割,支持使用逗号一次处理多个变量
statement
}graph TB init-->test test-->成功 成功-->for_body test-->失败 失败-->update update-->test
while
每次迭代都会调用判断循环条件
1
2
3
4
5
6expression //初始化
while (entry condition) //测试
{
statement(简单/{复合})
expression //更新
}第一次循环称为一次迭代
do while
当while循环前需要执行循环体的逻辑时,出口循环可以更简洁.
1
2
3
4do {
statement
}
while (expression);
condition:
- 非0为真
- 0为假
赋值运算符
=,+=,-=,*=,/=,%=
数组array/列表list
C编译器不检查数组索引的合理性,可能会将赋值超过索引的值存储在其它位置,可能破坏其它数据并导致程序出错.
数组可以使用下标subscript,索引indice,偏移量offset表示
1 | float ary[15];声明数组,含有15个float元素 |
第九章 函数
函数声明(函数原型funcation prototype)->函数定义
函数的返回值类型若与声明函数的类型不一致将转换成声明类型
sequenceDiagram participant main as 主调函数 participant call as 被调函数 opt 驱动程序 main->>call:实参 end opt 栈stack main->>main:参数 main->>call:被调函数从stack中读取参数值 end call-->>call:形参 call-->>main:return
递归recursion
函数调用自身,关键点是终止条件.
可以循环的一般都可以递归.
递归简洁,循环效高.
- 每次递归都创建新的变量(放入栈中)和作用域,占用更多的内存
- 每次递归都调用函数,初始化需要一定时间成本
递归要点:
- 每级函数调用都有自己的变量作用域.
- 每级函数调用到终止条件后逐级return.(套娃)
- 终止条件前的依次顺序执行,后面的逆序执行.
- 必须要终止条件
- 适用倒序计算(如计算一个整数的二进制)
尾递归:将递归调用放置在return前,相当于一个循环
指针
指针(pointer)用于存储变量的地址
一元&地址运算符给出变量的存储地址,var是变量,&var是变量var在内存的地址.printf 使用%p打印16进制地址
*间接运算符,找出存储在指针上的值
使用指针可以改变主调函数的值.
1 | int * pointer //声明指针的类型 |