附录一
附录一
再论指针和数组
再论指针和数组
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
预习检查
链表单元有哪几个部分组成
如何申请链表单元,及释放链表单元
实现单链表插入的基本语法
简述一下快速排序基本理论要点
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
课程目标
本章概述
重点
难点
指针与数组什么时候相同 C语言为什么把数组参数当作指针 C语言的多维数组,及如何创建动态数组。
本章目标
掌握指针什么时候和数组相同,以为容易混淆的原因
掌握多维数组的内存布局。
使用指针向函数传递多维数组参数
使用指针返回多维数组
使用指针创建和使用动态数组
指针和数组混淆的原因
指针传递多维数组参数
指针和数组混淆的原因
创建和使用动态数组
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
本章结构
再论指针和数组
再论指针和数组
怎样使用数组
怎样使用数组
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
指针与数组不相同
指针与数组不相同
指针与数组相同
指针与数组相同
指针运算 指针运算
指针数组和数组指针
指针数组和数组指针
函数指针和指针函数
函数指针和指针函数
1 再论指针和数组 指针与数组的不相同
指针与数组的相同
怎样使用指针
指针运算
函数指针和指针函数
指针数组和数组指针
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.1 指针与数组的不相同 数组和指针是如何访问的
数组访问指针数据
使声明与定义相匹配
数组和指针的其他区别
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.1.1数组和指针是如何访问的
申明区别
extern int *x; -》声明x是个int型的指针
extern int y[] -》y是个int型数组,长度尚未确定
地址和内容的区别
在这个上下文环境里 ,符号x的含义是x所 代表的地址。
在这个上下文环境里, 符号Y的含义是Y所代表 的地址的内容。
这被称为左值。
这被称为右值。
左值在编译时可知,
右值直到运行时才知。
左值表示存储结果的
如无特别说明, 右值
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
地方。 表示“Y的内容”。
X=Y
1.1.1数组和指针是如何访问的
数组下标引用特点
例:
图A
运行步骤:
地址在编译时可知
直接进行操作
数组:char a[9]=“abedefgh”; ... 取值:c=a[i]
9980
+1 +2 +3 +4 ... +i
编译器符号表具有一个地址9980 嵌入式家园 www.embedclub.com
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1. 取i的值,将它与9980相加 2. 取地址(9980+i)的内容。
1.1.2 数组访问指针数据 指针访问特点
图B
运行步骤:
例:
必须首先在运行时取得它的当前
值
间接进行操作
指针:char *p 取值:c=*p
5081
4642
5081
1. 取地址4624的内容,就是‘5081’ 2. 取地址5081的内容。
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git编译器符号表有一个符号p,它的
地址为4624 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.1.2 数组访问指针数据 数组访问指针特点
图C
运行步骤:
例:
对内存进行直接的引用转化为间接引用
数组:char a[9]=“abedefgh”; ... 取值:c=a[i]
5081
+1 +2 +3 ... +i
4642
5081
1. 取地址4624的内容,即‘5081’。 2. 取得i的值,并将它与5081相加。 3. 取地址[508l+i]的内容。
5081+i
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git编译器符号表有一个符号p,它的
地址为4624 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.1.2 数组访问指针数据
指针访问特点
char *p=“abcdefgh”;...p[3] -》 d char a[]=”abcdefgh”; ...a[3] -》 d
访问特点
取得符号表中P的地址,提取存储于此处的指针。 把下标所表示的偏移量与指针的值相加,产生一个地址。 访问上面这个地址,取得字符。
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.1.3 数组和指针的其他区别
保存数据的地址
指针 数组 保存数据
间接访问数据,首先取得指针的内容
,把它作为地址,然后从这个地
址提取数据。
直接访问数据,a[I]只是简单地以a*1为地址取得 数据
如果指针有一个下标[I],就把指针的 内容加上I作为地址,从中提取数 据
通常用于动态数据结构 相关的函数为malloc(),free()。
通常用于存储固定数目且数据类型相同的元素。
隐式分配和删除
自身即为数据名
通常指向匿名数据
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2 指针与数组的相同
什么时候指针与数组相同 混淆的原因
数组和指针规则 为什么C语言把数组形参当作指针 数组与指针归纳总结
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.1 什么时候指针与数组相同 数组运用特性
数组声明
外部数组(external array)的声明 数组的定义
函数参数的声明
运用特性 作为函数参数的数组名可以通过编译器转换为指针 使用数组时,数组可以写成指针 ,可以互换
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.1 什么时候指针与数组相同 数组与指针
编译器处理时是不同的 一个数组就是一个地址 一个指针就是一个地址的地址
在运行时的表示形式也是不一样的 可能产生不同的代码
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.2 数组和指针混淆的原因 分析:
char my _array[10]
char* my_ptr ;
...
j = strlen(my_array);
J = strlen(my_ptr);
printf(”%s %s”,my_ptr,my_array);
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.2 数组和指针混淆的原因 数组和指针是相同的规则
表达式中的数组名(与声明不同)被编译器当作一个指向该数组第一个元素 的指针1。
下标总是与指针的偏移量相同
在函数参数的声明中,数组名被编译器当作指向该数组第一个元素的指
针
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.3 数组和指针规则
“表达式中的数组名”就是指针 C语言把数组下标作为指针的偏移量 “作为函数参数的数组名”等同于指针
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.3.1 “表达式中的数组名”就是指针
数组下标的引用
一个指向数组的起始地址的指针加上偏移量” 下标值的步长调整到数组元素的大小
整型数的长度是4个字节,那么a[i+1]和a[i]在内存中的距离就是4(而不是1)
例:访问a[i]: int a[10];
int*p; Int i=2 ;
p = a;
访问数组第i个元素的三张方式 p = a;
p = a+i; *p;
p[i];
*(p+i);
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.3.1 “表达式中的数组名”就是指针 数组的引用不能用指向该数组第一个元素的指针规则
数组作为sizeof()的操作数一显然此时需要的是整个数组的大小,而不是 指针所指向的第一个元素的大小。
使用&操作符取数组的地址。 数组是一个字符串(或宽字符串)常量初始值。
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.3.2 C语言把数组下标作为指针的偏移量 数组访问模式分析
数组访问
for(i=0;i<10;i++)
把[R2]装入R3
A[i]=0;
如果需要,对R3的步长进行调整把 R1+R3
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
把左值(a)装入Rl(可以提到循环外)
把左值(i)装入R2(可以提到循环外)
的结果装入R4中 把0存储到[R4]
1.2.3.2 C语言把数组下标作为指针的偏移量 数组访问模式分析
p=a;
把左值(i)装入R2(可以提到循环外)
指针备选方案1
for(i=0;i<10;i++)
把[R2]装入R3
p[i]=0;
把左值(p)装入R0(可以提到循环外)
把[R0]装入Rl(可以提到循环外)
如果需要,对R3的步长进行调整
把R1+R3的结果装入R4中 嵌入式家园 www.embedclub.com
把0存储到[R4]。 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.3.2 C语言把数组下标作为指针的偏移量 数组访问模式分析
p=a;
把左值(i)装入R2(可以提到循环外)
指针备选方案1
for(i=0;i<10;i++)
把[R2]装入R3
*p++=0;
把左值(p)装入R0(可以提到循环外)
把[R0]装入Rl(可以提到循环外)
如果需要,对R3的步长进行调整
把R1+R3的结果装入R4中 嵌入式家园 www.embedclub.com
把0存储到[R4]。 git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.3.2 C语言把数组下标作为指针的偏移量 数组访问模式分析
p=a;
指针备选方案2
把[R0]装入Rl *(p+i)=0; 把0存储至U[R1]
for(i=0;i<10;i++)
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
把P所指对象的大小装入R5 (可以提到循环外)
把左值(p)装入Rl(可以提到循环外)
把R5+R1的结果装入Rl 把Rl存储到[R0]
1.2.4 为什么C语言把数组形参当作指针 数组运用特性
数组声明
外部数组(external array)的声明 数组的定义
函数参数的声明
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.4 为什么C语言把数组形参当作指针
出于效率的考虑 ???
传值调用与传址调用
C语言形参特性 非数组形式的数据实参均以传值形式
拷贝整个数据
拷贝整个数组,在时间上还是在内存空间上的开销都非常大
所有的数组在作为参数传递时都转换为指向数组起始
地址的指针,而其他的参数均采用传值调用
函数的返回值绝不能是一个函数数组,而只能是指向
数组或函数的指针
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.4 为什么C语言把数组形参当作指针 例:
展示了对一个下标形式的数组形参进行访问所需要的几个步骤。
Func(char p[]); ... c=p[i]
Func(char *p); ... c=p[i] 编译器符号表显示p可以取址,从堆栈指针sp偏移14个位置运行时
步骤1:从sp偏移14个位置找到函数的活动记录,取出实参。 步骤2:取i的值,并与5081相加。 步骤3:取出地址(508+i)的内容。
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.2.4 为什么C语言把数组形参当作指针 数组,指针实参的一般用法
调用时的实参
类 型
通常目的
func(&my_int); func(my_int_ptr); func(my_int_array);
一个整型数的地址
指向整型数的指针
整型数组
一个int参数的传址调用
传递一个数组 func(&my_int_array[i]) 一个整型数组某个元素的地址 传递数组的一部分
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
传递一个指针
1.2.5 数组与指针归纳总结 用a[i]这样的形式对数组进行访问总是被编译器“改写”或解
释为像*(a+1)这样的指针访问。 指针始终就是指针。它绝不可以改写成数组。
在特定的上下文中,也就是它作为函数的参数(也只有这 种情况),一个数组的声明可以看作是一个指针。作为函数 参数的数组(就是在一个函数调用中)始终会被编译器修改 成为指向数组第一个元素的指针。
当把一个数组定义为函数的参数时,可以选择把它定义为
数组,也可以定义指针。不管选择哪种方法,在函数内部
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git事实上获得的都是一个指针。
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git定义和声 必须 配
1.3 怎样使用数组
多维数组
向函数传递一个多维数组
从函数返回一个数组
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.3.1 多维数组
多维数组特性
多维数组内存布局
如何分解多维数组
如何对数组进行初始化
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.3.1.1 多维数组特性
定义和引用多维数组惟一的方法就是使用数组的数组 注意:a[i][j][k] 与 a[I,j,k] 多维数组看作是一种向量
多维数组的定义
声明一个10×20的多维字符数组 char carrot[10][20];
或者声明一种看上去更像“数组的数组”形式: typedef char vegetable[20];
vegetable carrot[10];
不论哪种情况,访问单个字符都是通过carrot[i][j]的形式, 编译器在编译时会把它解析为*(*(carrot+i)+j)的形式
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.3.1.2 多维数组的内存布局
多维数组内存布局 pea[1][2]的内存表示:线性存储 表达式为:*(*(pea+i)+j)
Pea[1][2]
‘a’
...
Pea[0] 嵌入式家园Peaw[1w]w.embedcluPbe.cao[o1m] git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
Pea[0] [1] [2] [3]
‘a’
Pea[1]
1.3.1.3 如何分解多维数组
分解特点:
多维数组是如何分解为几个单独的数组的
多维数组每一个单独的数组都可以看作是一个指针
不能把一个数组赋值给另一个数组
多维数组分解
int apricot[2][3][5] sizeof(apricot) 区域
sizeof(apricot[i]) sizeof(apricot[i][j]) sizeof(apricot[i][j][k])
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.3.1.4 如何对数组进行初始化 嵌套的花括号进行初始化多维数组
如1
short cantaloupe[2][5]={ {10,12,3,4,一5}, {31,22,6,0,-5}, };
如2
int rhubarb[][3]={{0,0,0},{1,1,1},};
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.3.1.4 如何对数组进行初始化 建立指针数组进行初始化多维数组
如1
char vegetables[ ][9] = { “carrot”,
只有字符串常量才可以初始化指
针数组
“celery”, “corn”, “cilantro”,
指针数组不能由非字符串的类型
如2 “crispyfriedpatatoes”}
int *weights[]={ {1,2,3,4,5},
char *vegetables[]= { “carrot”,
};
“celery”,
“corn”,
“cilantro”,
嵌入式家园 www.embedclub.com
“crispy fried patatoes” }
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
直接初始化
{6,7}, {8,9,10}
1.3.1.4 如何对数组进行初始化 建立数组进行初始化多维数组
如:
int row_1[]={1,2,3,4,5,-1}; /*一1是行结束标志*/ int row_2[]={6,7,-1};
int row_3[]={8,9,10,-1};
int *weight[]=
{
row_1,
row_3 };
row_2,
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.3.2 向函数传递一个多维数组 方法1
例子
模式:my_function(int my_array[10][20]);
特点: 最简单的方法
作用最小的
int a[3][3] =
};
{3, 3, 3}
Func(a[3][3]);
int a[3][3] =
Main() {Main()
{{
{1, 1, 1},
{
......
};
......
{1, 1, 1},
......
// 函数调用
{2, 2, 2},
{2, 2, 2},
{3, 3, 3}
// 函数调用 Func(a[3][3]);
// 函数定义 // 函数定义
...... 上海嵌{入...式...家} 园-开发板商城 http://embedclub.taobao.com/
嵌入式家园 www.embedclub.c}omvoid Func(int array[3][3]); }
void Func(int array[3][3]);
{ ...... }
1.3.2 向函数传递一个多维数组 方法2
模式:my_function(int my_array[][20]) ; 例:
方法3 (指针传递模式) 模式:my_function(char **my_array)
int a[3][3] = {int a[3][3] =
Main() {Main()
};
{3, 3, 3}
// 函数调用 Func(a);
{
{1, 1, 1},
};
Func(a);
{1, 1, 1},
{
......
{2, 2, 2},
......
// 函数调用
{2, 2, 2},
{3, 3, 3}
// 函数定义 // 函数定义
......
嵌入式家园 www.embedclub.com
void Func(int **array); } void Func(int **array);
}
{ ...... }
上海嵌{入...式...家} 园-开发板商城 http://embedclub.taobao.com/
......
1.3.3 从函数返回一个数组
怎样返回一个数组
例:
一个指向任何数据结构的指针
一个指向数组的指针
int(*pal())[20]; int(*pal())[20] {
}
return pear;
嵌入式家园 www.embedclub.com
/*声明一个指向包含20个int元素的数组的指针*/ int(*pear)[20];
pear=calloc(20,sizeof(int)); if(!pear)longjmp(error,1);
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
阶段小节
数组在什么时候和指针相同
数组与指针混淆原因是什么
数组当作函数传递的好处是什么 如何向一个函数传递一维数组
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4 指针运算
什么是间接引用
最多可以使用几层指针
void指针与空指针 指针运算
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.1 什么是间接引用
间接引用: 指向变量或内存中的对象的指针 指针就是对对象值的间接引用
一个间接引用的例子
#include <stdio.h> Int main()
{
int i;
int * p ; i = 5;
p=&i; /* now *p==i */
/* %PisdescribedinFAQVII.28*/
printf("i=%d, p=%P , * p= %d " , i, P , *p);
*p=6; /* sameasi=6 */
printf("i=%d, p=%P , * p= %d " , i, P , *P);
return0; /* seeFAQXVI.4 */}
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
}
1.4.2 最多可以使用几层指针
一个指针时最多可以包含几层间接引用
至少可以有12层 如:
不要使用两层以上的指针
int i=0;
int * ip0l
= &d;
= &ip01;
int ** ip02
int ***ip03
= &ip02; = &dp03;
int **** ip04
int ***** ip05
= &ip04;
最多可以使用多少层指针而不会使程序变得难读
int ****** ip06 = &ip05;
int ******* ip07 = &ip06;
程序运行时最多可以有几层指针
无限层
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.2 最多可以使用几层指针 例:一个有无限层间接引用的循环链表
/*Would run forever if you didn't limit it to MAX */ # include <stdio. h>
struct circ_list
{
# define MAX 20 main()
{
char value[ 3 ];
struct circ_list * next; };
int i = 0;
struct circ_list while (i <=MAX)
*p = suffixes;
struct circ_list suffixes[ ] = { "th",&.suffixes[1],/* Oth */
{
printf("%ds% ", i, p->value); + +i;
p = p->next;
"st",&.suffixes[2],/* 1st */
"nd",&suffixes[3],/* 2nd */
"rd",&suffixes[4],/* 3rd */
"th", &.suffixes[ 5 ], / * 4th * /
} }
"th",&.suffixes[6],/* 5th */
"th",&suffixes[7],/* 6th */
"th",&suffixes[8],/* 7th */
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git"th", &suffixes[9],/* 8th */
"th",&suffixes[0],/* 9th */};
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.3 void指针与空指针
什么是空指针 什么是void指针 NULL总是被定义为0吗
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.3.1 什么是空指针 空指针
并不指向任何对象指针
值是NULL , NULL可能是0,0L或(void*)0 绝对不能间接引用一个空指针
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.3.1 什么是空指针 空指针的用法
用空指针终止对递归数据结构的间接引用
用空指针作函数调用失败时的返回值
用空指针作警戒值
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.3.2 什么是void指针
void指针 通用指针或泛指针
不属于任何类型
常常用作函数指针
内存操作
内存操作 例子
char *strepy(char‘strl,const char *str2);
char *strncpy(char *strl,const char *str2,size_t n); void *memcpy(void *addrl,void *addr2,size_t n);
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.3.3 NULL总是被定义为0吗 NULL与 0
NULL不是被定义为0,就是被定义为(void *)0
if(/* ... */) {
p=NULL; }
else {
p=/* something else */; }
/* ... */ if(p==0)
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.4 指针运算
两个指针可以相减吗
把一个值加到一个指针上意味着什么
两个指针可以相加吗
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.4.1 两个指针可以相减吗 如果两个指针向同一个数组,它们就可以相减,其为
结果为两个指针之间的元素数目
如果两个指针不是指向一个数组,它们相减就没有意 义
指针相减的结果是某种整类型的值
ptrdiff_t
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.4.1 两个指针可以相减吗 指针的相减运算
# include <stdio. h> # include <stddef.h> struct stuff
{
main ( ) {
char name[l6]; };
* p8 = &-array[8];
diff = p8-p0;
addr.diff = (char * ) p8 - (char * ) p0;
struct stuff array [] = {
};
printf ("p0 + 8 = %P (same as p8) ", (void* ) (p0 + 8)); return0; /* seeFAQXVI.4 */
{ "The" }, { "quick" },
{ "brown" }, { "fox" },
{ "jumped" }, { "over" }, { "the" }, { "lazy" }, {"dog." }, {""}
addr_diff); printf ("p8-8 = %P " , (void*) (p8-8));
}
struct stuff
struct stuff
ptrdiff_t
ptrdiff_t
printf ("&array[0] = p0 = %P " , (void* ) p0);
printf ("&. array[8] = p8 = %P " , (void* ) p8) ;
printf ("The difference of pointers is %ld " , (long) diff) ; printf ("The difference of addresses is %ld " , (long)
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
* p0 = &.array[0];
1.4.4.2 把一个值加到一个指针上意味着什么 当把一个整型值加到一个指针上后,该指针指向的位
置就向前移动了一段距离
这段距离对应的字节数等于该值和该指针所指向的对
象的大小的乘积
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.4.4.3 两个指针可以相加吗 两个指针是不能相加的
如:
p=(p+p2)-p1;
正确的语句应该是: p=p+(p2-p1); 对此例来说,使用下述语句更好: p+=p2-p1;
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.5 函数指针和指针函数
指针函数
函数指针
函数指针的用法
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.5.1 指针函数 定义:
指带指针的函数,即本质是一个函数
语法:
返回类型标识符 * 返回名称(形式参数表) { 函数体 }
特点:
返回类型可以是任何基本类型和复合类型
返回一个指针变量的值
可以把整个函数看成一个变量
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.5.1 指针函数 例子:
#include “stdio.h” float *find(); main()
{
函数定义:
}
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
static float score[][4]={{60,70,80,90}, {56,89,34,45},
/*定义指针函数*/
float * find(float(*pionter)[4],int n)
{
{34,23,56,45}};
float *pt;
float *p;
int i,m;
printf("Enter the number to be found:"); scanf("%d",&m);
printf("the score of NO.%d are: ",m); p=find(score,m);
for(i=0;i<4;i++)
pt=*(pionter+n); return(pt);
printf("%5.2f ",*(p+i));
}
1.5.2 函数指针 定义:
指向函数的指针变量 语法:
数据类型标志符 (*指针变量名)(参数)
特点:
是指针变量
指向类型为函数
可用该指针变量调用函数
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.5.2 函数指针 例子:
函数定义:
void main() {
/*定义函数*/
int max(int x,int y) {
}
int (*ptr)();
int a,b,c;
ptr=max;
scanf("%d,%d",&a,&b); c=(*ptr)(a,b); printf("a=%d,b=%d,max=%d",a,b,c);
return(x>y?x:y); }
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.6 函数指针的用法
定义函数指针类型
// 定义一个原型为int Fun( int a );的函数指针 typedef int (*PTRFUN) ( int aPara );
函数指针变量的定义
PTRFUN pFun; // pFun 为函数指针变量名
int (*pFun2) ( int a ); // pFun2也是函数指针变量名
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
1.6 函数指针的用法
函数指针作为函数的参数传递
定义回调函数
使用回调
int CallBack( int a ){ return ++a;
}
定义回调者函数
void Caller( PTRFUN cb ) // void Caller( int (*cb) ( int ) ) // 也可这样申明 {
}
int nPara = 1;
int nRet = cb( nPara );
void Test(){
Caller( CallBack ); // 直接使用回调函数
PTRFUN cb = CallBack; // int (*cb) ( int ); cb = CallBack;
int nRet1 = cb( 99 ); // nRet1 = 100;
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
}
阶段小节
指针在什么时候可以实现相加减 空指针与void指针
指针函数的申明和赋值 函数指针的传递和调用 指针数组的定义和初始化
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
本章总结
再论指针和数组
再论指针和数组
深入具体的讲述指针的运算
指针与数组不相同
指针与数组不相同
指针与数组相同
指针与数组相同
讲述了指针和数组的相同点,
以及分析他们之间的混淆原因
怎样使用数组
怎样使用数组
简单讲述了多维数组,并深入
讲述数组和函数的应用
指针运算 指针运算
函数指针和指针函数
函数指针和指针函数
了解指针函数和函数指针的区
别,并深入讲述函数指针的用
法
指针数组和数组指针
指针数组和数组指针
了解指针数组和数组指针的区
别
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git
本节主要讲述了指针和数组
的互访及其区别
实验项目
题目
写一个排序函数,要求实用两种参数传递模式。并采用函数指针
调用模式实现的排序函数,并输入排序的最终结果
实验目的
回顾上章节的排序算法应用;
数组的参数传递和数组及指针互用操作;
函数指针的实现和调用;
实验分析
定义排序函数,采用传指针和传数组两种方式; 用typedef定义函数指针;
调用函数指针;
输出最终的排序结果;
git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.gitgit@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git