logo资料库

C高级编程讲义-传智播客.doc

第1页 / 共130页
第2页 / 共130页
第3页 / 共130页
第4页 / 共130页
第5页 / 共130页
第6页 / 共130页
第7页 / 共130页
第8页 / 共130页
资料共130页,剩余部分请下载后查看
1.前言
1.1 战前准备
1.1.1 听课要求
1.2 技术层次
1.3 过程的封装设计
2.C语言概述
1.1 C语言的起源
1.2 使用C语言的理由
1.3 C语言标准
1.3.1 K&R C
1.3.2 ANSI C/C89标准
1.3.3 C99标准
3. 内存分区
3.1 数据类型
3.1.1 数据类型概念
3.1.2 数据类型别名
3.1.3 void数据类型
3.1.4 sizeof操作符
3.1.5 数据类型总结
3.2 变量
3.1.1 变量的概念
3.1.2 变量名的本质
3.3 程序的内存分区模型
3.3.1 内存分区
3.3.1.1 运行之前
3.3.1.1 运行之后
3.3.2 分区模型
3.3.2.1 栈区
3.3.2.2 堆区
3.3.2.3 全局/静态区
3.3.2.4 总结
3.3.3 函数调用模型
3.3.3.1 函数调用流程
3.3.3.2 调用惯例
3.3.3.2 函数变量传递分析
3.3.4 栈的生长方向和内存存放方向
4.指针强化
4.1 指针是一种数据类型
4.1.1 指针变量
4.1.2 野指针和空指针
4.1.2.1 空指针
4.1.2.2 野指针
4.1.3 间接访问操作符
4.1.4 指针的步长
4.2 指针的意义_间接赋值
4.2.1 间接赋值的三大条件
4.2.2 如何定义合适的指针变量
4.2.3 间接赋值:从0级指针到1级指针
4.2.4 间接赋值:从1级指针到2级指针
4.2.4 间接赋值的推论
4.3 指针做函数参数
4.3.1 输入特性
4.3.2 输出特性
4.4 字符串指针强化
4.4.1 字符串指针做函数参数
4.4.1.1 字符串基本操作
4.4.1.2 字符串拷贝功能实现
4.4.1.3 字符串反转模型
4.4.2字符串的格式化
4.4.2.1 sprintf
4.4.2.2 sscanf
4.5 一级指针易错点
4.5.1 越界
void test(){
char buf[3] = "abc";
printf("buf:%s\n",buf);
}
4.5.2 指针叠加会不断改变指针指向
void test(){
char *p = (char *)malloc(50);
char buf[] = "abcdef";
int n = strlen(buf);
int i = 0;
for (i = 0; i < n; i++)
{
*p = buf[i];
p++; //修改原指针指向
}
free(p);
}
4.5.3 返回局部变量地址
char *get_str()
{
char str[] = "abcdedsgads"; //栈区,
printf("[get_str]str = %s\n", str);
return str;
}
4.5.4 同一块内存释放多次(不可以释放野指针)
void test(){
char *p = NULL;
p = (char *)malloc(50);
strcpy(p, "abcdef");
if (p != NULL)
{
//free()函数的功能只是告诉系统 p 指向的内存可以回收了
// 就是说,p 指向的内存使用权交还给系统
//但是,p的值还是原来的值(野指针),p还是指向原来的内存
free(p);
}
if (p != NULL)
{
free(p);
}
}
4.6 const使用
5. 指针的指针(二级指针)
5.1 二级指针基本概念
5.2 二级指针做形参输出特性
5.3 二级指针做形参输入特性
5.4 强化训练_画出内存模型图
5.4 多级指针
6.位运算
6.1位逻辑运算符
6.1.1按位取反~
6.1.2位与(AND): &
6.1.3位或(OR): |
6.1.4位异或:
6.1.5用法
6.1.5.1 打开位
6.1.5.2 关闭位
6.1.5.3 转置位
6.1.5.4 交换两个数不需要临时变量
6.2 移位运算符
6.2.1 左移 <<
6.2.2 右移 >>
6.2.3 用法:移位运算符
6. 多维数组
6.1 一维数组
6.1.1 数组名
6.1.2 下标引用
6.1.3 数组和指针
6.1.4 作为函数参数的数组名
6.2 多维数组
6.2.1 数组名
6.2.2 指向数组的指针(数组指针)
6.2.3 指针数组(元素为指针)
5.3.1 栈区指针数组
5.3.2 堆区指针数组
6.2.4二维数组三种参数形式
6.2.4.1 二维数组的线性存储特性
6.2.4.2 二维数组的3种形式参数
6.3总结
6.3.1 编程提示
6.3.2 内容总结
7.结构体
7.1 结构体基础知识
7.1.1 结构体类型的定义
7.1.2 结构体变量的定义
7.1.3 结构体变量的初始化
7.1.4 结构体成员的使用
7.1.5结构体赋值
7.1.5.1 赋值基本概念
7.1.5.1 深拷贝和浅拷贝
7.1.6 结构体数组
7.2 结构体嵌套指针
7.2.1 结构体嵌套一级指针
7.2.2 结构体嵌套二级指针
7.3 结构体成员偏移量
7.4 结构体字节对齐
7.4.1 内存对齐
7.4.1.1 内存对齐原因
7.4.1.1 如何内存对齐
7.4.2 内存对齐案例
8.文件操作
8.1文件相关概念
8.1.1 文件的概念
8.1.2 流的概念
8.1.2.1 文本流
8.1.2.1 二进制流
8.2文件的操作
8.2.1 文件流总览
8.2.2 文件指针
8.2.3 文件缓冲区
8.2.4 文件打开关闭
8.2.4.1 文件打开(fopen)
8.2.4.2 文件关闭(fclose)
8.2.4 文件读写函数回顾
8.2.4.1 字符读写函数回顾
8.2.4.2 行读写函数回顾
8.2.4.3 块读写函数回顾
8.2.4.4 格式化读写函数回顾
8.2.5.5 随机读写函数回顾
8.4 文件读写案例
8.4.1 读写配置文件
9.链表
9.1 链表基本概念
9.1.1 什么是链表
9.1.2 有关结构体的自身引用
9.1.3 链表节点
9.1.4 链表的分类
9.1.4.1 静态链表
9.1.4.2 动态链表
9.1.4.3 带头和不带头链表
9.1.4.4 单向链表、双向链表、循环链表
9.2 链表基本操作
9.2.1 创建链表
9.2.2 遍历链表
9.2.3 插入节点
9.2.4 删除节点
9.2.5 销毁链表
10.函数指针和回调函数
10.1 函数指针
10.1.1 函数类型
10.1.2 函数指针(指向函数的指针)
10.1.3 函数指针数组
10.1.4 函数指针做函数参数(回调函数)
11.预处理
11.1 预处理的基本概念
11.1 文件包含指令(#include)
11.1.1 文件包含处理
11.1.2 #incude<>和#include""区别
11.2 宏定义
11.2.1 无参数的宏定义(宏常量)
11.2.2 带参数的宏定义(宏函数)
11.3 条件编译
11.3.1 基本概念
11.3.2 条件编译
11.4 一些特殊的预定宏
12.动态库的封装和使用
12.1 库的基本概念
12.2 windows下静态库创建和使用
12.2.1 静态库的创建
12.2.2 静态库的使用
12.2.3 静态库优缺点
12.3 windows下动态库创建和使用
12.3.1 动态库的创建
12.3.2 动态库的使用
13. 递归函数
13.1 递归函数基本概念
13.2 普通函数调用
13.3 递归函数调用
13.4 递归实现字符串反转
14 面向接口编程
14.1案例背景
14.2 案例需求
14.3 案例要求
14.4 编程提示
1. 前言 企业需要能干活的人,需要能上战场的兵。 1.1 战前准备 1.1.1 听课要求  专心听讲、积极思考;  遇到不懂的暂时先记下,课后再问;  建议准备一个笔记本(记录重点、走神的时间);  当堂动手运行,不动手,永远学不会;  杜绝边听边敲(如果老师讲的知识点很熟,你可以边听边敲)、杜绝犯困听课。  如果时间允许,请课前做好预习;  从笔记、代码等资料中复习上课讲过的知识点。尽量少回看视频,别对视频产生依 赖,可以用 2 倍速度回看视频;  按时完成老师布置的练习,记录练习中遇到的 BUG 和解决方案,根据自己的理解 总结学到的知识点;  初学者 应该抓住重点,不要钻牛角尖遇到问题了,优先自己尝试解决,其次谷歌 百度,最后再问老师;  如果时间允许,可以多去网上找对应阶段的学习资料面试题,注意作息,积极锻炼。 1
1.2 技术层次 对于解决问题的解决方案有清晰的架构图,那么对于技术学习也要分清层次: 1.3 过程的封装设计 //打印函数 void PrintArray(int arr[],int len){ //打印 for (int i = 0; i < len; i++){ printf("%d ", arr[i]); } printf("\n"); } void MySort(int arr[],int len){ //排序 for (int i = 0; i < len; i++){ for (int j = len - 1; j > i; j--){ if (arr[j] < arr[j - 1]){ int temp = arr[j]; 2
arr[j] = arr[j - 1]; arr[j - 1] = temp; } } } } void test(){ int arr[] = { 10, 50, 20, 90, 30 }; int len = sizeof(arr) / sizeof(int); PrintArray(arr, len); MySort(arr, len); PrintArray(arr, len); } 2. C 语言概述 欢迎大家来到 c 语言的世界,c 语言是一种强大的专业化的编程语言。 1.1 C 语言的起源 贝尔实验室的 Dennis Ritchie 在 1972 年开发了 C,当时他正与 ken Thompson 一起设 计 UNIX 操作系统,然而,C 并不是完全由 Ritchie 构想出来的。它来自 Thompson 的 B 语言。 1.2 使用 C 语言的理由 在过去的几十年中,c 语言已成为最流行和最重要的编程语言之一。它之所以得到发展, 是因为人们尝试使用它后都喜欢它。过去很多年中,许多人从 c 语言转而使用更强大的 c++ 3
语言,但 c 有其自身的优势,仍然是一种重要的语言,而且它还是学习 c++的必经之路。  高效性。c 语言是一种高效的语言。c 表现出通常只有汇编语言才具有的精细的控 制能力(汇编语言是特定 cpu 设计所采用的一组内部制定的助记符。不同的 cpu 类 型使用不同的汇编语言)。如果愿意,您可以细调程序以获得最大的速度或最大的 内存使用率。  可移植性。c 语言是一种可移植的语言。意味着,在一个系统上编写的 c 程序经过 很少改动或不经过修改就可以在其他的系统上运行。  强大的功能和灵活性。c 强大而又灵活。比如强大灵活的 UNIX 操作系统便是用 c 编写的。其他的语言(Perl、Python、BASIC、Pascal)的许多编译器和解释器也都 是用 c 编写的。结果是当你在一台 Unix 机器上使用 Python 时,最终由一个 c 程 序负责生成最后的可执行程序。 1.3 C 语言标准 1.3.1 K&R C 起初,C 语言没有官方标准。1978 年由美国电话电报公司(AT&T)贝尔实验室正式发 表了 C 语言。布莱恩·柯林汉(Brian Kernighan) 和 丹尼斯·里奇(Dennis Ritchie) 出 版了一本书,名叫《The C Programming Language》。这本书被 C 语言开发者们称为 K&R,很多年来被当作 C 语言的非正式的标准说明。人们称这个版本的 C 语言为 K&R C。 K&R C 主要介绍了以下特色:结构体(struct)类型;长整数(long int)类型;无符 号整数(unsigned int)类型;把运算符=+和=-改为+=和-=。因为=+和=-会使得编译器 不知道使用者要处理 i = -10 还是 i =- 10,使得处理上产生混淆。 4
即使在后来 ANSI C 标准被提出的许多年后,K&R C 仍然是许多编译器的最准要求, 许多老旧的编译器仍然运行 K&R C 的标准。 1.3.2 ANSI C/C89 标准 1970 到 80 年代,C 语言被广泛应用,从大型主机到小型微机,也衍生了 C 语言的很 多不同版本。1983 年,美国国家标准协会(ANSI)成立了一个委员会 X3J11,来制定 C 语言标准。 1989 年,美国国家标准协会(ANSI)通过了 C 语言标准,被称为 ANSI X3.159-1989 "Programming Language C"。因为这个标准是 1989 年通过的,所以一般简称 C89 标 准。有些人也简称 ANSI C,因为这个标准是美国国家标准协会(ANSI)发布的。 1990 年,国际标准化组织(ISO)和国际电工委员会(IEC)把 C89 标准定为 C 语言 的国际标准,命名为 ISO/IEC 9899:1990 - Programming languages -- C[5] 。因为此 标准是在 1990 年发布的,所以有些人把简称作 C90 标准。不过大多数人依然称之为 C89 标准,因为此标准与 ANSI C89 标准完全等同。 1994 年,国际标准化组织(ISO)和国际电工委员会(IEC)发布了 C89 标准修订版, 名叫 ISO/IEC 9899:1990/Cor 1:1994[6] ,有些人简称为 C94 标准。 1995 年,国际标准化组织(ISO)和国际电工委员会(IEC)再次发布了 C89 标准修 订版,名叫 ISO/IEC 9899:1990/Amd 1:1995 - C Integrity[7] ,有些人简称为 C95 标准。 1.3.3 C99 标准 5
1999 年 1 月,国际标准化组织(ISO)和国际电工委员会(IEC)发布了 C 语言的新标 准,名叫 ISO/IEC 9899:1999 - Programming languages -- C ,简称 C99 标准。这是 C 语言的第二个官方标准。 例如: 增加了新关键字 restrict,inline,_Complex,_Imaginary,_Bool 支持 long long,long double _Complex,float _Complex 这样的类型 支持了不定长的数组。数组的长度就可以用变量了。声明类型的时候呢,就用 int a[*] 这 样的写法。不过考虑到效率和实现,这玩意并不是一个新类型。 3. 内存分区 3.1 数据类型 3.1.1 数据类型概念 什么是数据类型?为什么需要数据类型? 数据类型是为了更好进行内存的管理,让编译器能确定分配多少内存。 我们现实生活中,狗是狗,鸟是鸟等等,每一种事物都有自己的类型,那么程序中使用 数据类型也是来源于生活。 6
当我们给狗分配内存的时候,也就相当于给狗建造狗窝,给鸟分配内存的时候,也就是 给鸟建造一个鸟窝,我们可以给他们各自建造一个别墅,但是会造成内存的浪费,不能很好 的利用内存空间。 我们在想,如果给鸟分配内存,只需要鸟窝大小的空间就够了,如果给狗分配内存,那 么也只需要狗窝大小的内存,而不是给鸟和狗都分配一座别墅,造成内存的浪费。 当我们定义一个变量,a = 10,编译器如何分配内存?计算机只是一个机器,它怎么知 道用多少内存可以放得下 10? 所以说,数据类型非常重要,它可以告诉编译器分配多少内存可以放得下我们的数据。 狗窝里面是狗,鸟窝里面是鸟,如果没有数据类型,你怎么知道冰箱里放得是一头大象! 数据类型基本概念:  类型是对数据的抽象;  类型相同的数据具有相同的表示形式、存储格式以及相关操作;  程序中所有的数据都必定属于某种数据类型;  数据类型可以理解为创建变量的模具: 固定大小内存的别名; 7
3.1.2 数据类型别名 示例代码: typedef unsigned int u32; typedef struct _PERSON{ char name[64]; int age; }Person; void test(){ u32 val; //相当于 unsigned int val; Person person; //相当于 struct PERSON person; } 3.1.3 void 数据类型 void 字面意思是”无类型”,void* 无类型指针,无类型指针可以指向任何类型的数据。 void 定义变量是没有任何意义的,当你定义 void a,编译器会报错。 void 真正用在以下两个方面:  对函数返回的限定;  对函数参数的限定; 示例代码: //1. void 修饰函数参数和函数返回 void test01(void){ printf("hello world"); } //2. 不能定义 void 类型变量 void test02(){ void val; //报错 } 8
分享到:
收藏