第六章 指针 指针的概念 指针变量 指针与数组 指针与函数 返回指针值的函数.

Slides:



Advertisements
Similar presentations
第九章 指针 西安工程大学.
Advertisements

第七章 指针 计算机公共教学部.
第十章 指针 分析C程序的变量所存放的数据:  数值型数据:整数、实数  字符型数据:字符、字符串 这些变量具有以下性质:
第7章 指针 存储地址的变量的类型就是指针类型 能直接对内存地址操作, 实现动态存储管理 容易产生副作用, 初学者常会出错
第七章 指针 教 材: C程序设计导论 主 讲: 谭 成 予 武汉大学计算机学院.
二级指针与二维数组.
C语言程序设计基础 第10章 指针进阶 刘新国.
10.1 二级指针 10.2 指针与二维数组 10.3 指针的动态存储分配 10.4 函数指针 10.5 main函数的参数
C语言程序设计教程 单位:德州学院计算机系.
第8章 指针 21世纪高等学校精品规划教材.
第 6 章 第 6 章 指 针 指 针 1.
第8章 指针 ● 8.1 指针简介 ● 8.2 指针变量的操作 ● 8.3 数组与指针 ● 8.4 二维数组与指针 ●本章小结 ●本章练习.
C语言基础——指针的高级应用 Week 05.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
6.4 字符串与指针 1. 用字符数组存放一个字符串.
第六节 二维数组和指针 二维数组的地址 对于一维数组: (1)数组名array表示数组的首地址, 即array[0]的地址;
8.1 指针的概念 8.2 指针变量 8.3 指针变量的基础类型 8.4 指针的运算 8.5 指针与一维数组 8.6 指针应用实例
第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
程序设计基础.
第6章 指针 学习目的与要求: 了解指针的概念和相关术语 熟练掌握指向变量、数组和字符串的指针变量的使用方法 了解指向函数的指针变量
指 针 为什么要使用指针 指针变量 指针与数组 返回指针值的函数 动态内存分配 通过指针引用字符串 指向函数的指针 小 结 习 题.
目录 10.1 指针的基本概念 10.2 指向变量的指针变量 10.3 指向数组的指针变量 10.4 指向函数的指针变量和指针型函数
第八章 指 针 8.1 指针的概念与定义 8.2 指针作函数参数 8.3 指针与数组 8.4 指针与函数 8.5 复杂指针.
第 十 章 指 针.
项目六 用指针优化学生成绩排名 项目要求 项目分析
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
第八章 函数.
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
第五章 指针 5.1 指针的概念和定义 5.2 指针运算 5.3 指针和数组 5.4 字符串指针 5.5 指针数组 5.6 指向指针的指针
二维数组的指针表示 与复杂的指针例子 专题研讨课之三.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第8章 指针.
第八章 使用指针.
第十章 指针.
欲穷千里,更上层楼 第十章 指 针 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环,
第五章 习题课 电子信息与计算机科学系 曾庆尚.
C++大学基础教程 第6章 指针和引用 北京科技大学 信息基础科学系.
9.1 地址、指针和变量 9.2 指针运算 9.3 指针与数组 9.4 函数与指针 9.5 程序综合举例 9.6 上机实训.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C语言复习3----指针.
C语言大学实用教程 第6章 数组 西南财经大学经济信息工程学院 刘家芬
C语言大学实用教程 第7章 指针 西南财经大学经济信息工程学院 刘家芬
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
指针 几个概念:  指针也是一种数据类型,具有指针类型的变量,称为指针变量。
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第6讲 指针与引用 6.1 指针 6.2 引用.
C语言程序设计 第一章 数据类型, 运算符与表达式 第二章 顺序程序设计 第三章 选择结构程序设计 第四章 循环控制 第五章 数组.
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。
C程序设计.
第4章 Excel电子表格制作软件 4.4 函数(一).
第九章 指针.
第九节 赋值运算符和赋值表达式.
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C程序设计.
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
C语言程序设计 第8章 指针.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第九章 指针 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第八章 指 针 北京邮电大学出版社.
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
Presentation transcript:

第六章 指针 指针的概念 指针变量 指针与数组 指针与函数 返回指针值的函数

前言 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值

6.1 指针的概念 变量与地址 i k 程序中: int i; float k; 变量是对程序中数据 存储空间的抽象 6.1 指针的概念 变量与地址 内存中每个字节有一个编号-----地址 …... 2000 2001 2002 2005 内存 2003 程序中: int i; float k; i 编译或函数调用时为其分配内存单元 k 变量是对程序中数据 存储空间的抽象

指针与指针变量 指针:一个变量的地址 指针变量:专门存放变量地址的变量叫~ 10 变量的内容 变量的地址 指针变量 变量地址(指针) …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 变量的内容 变量的地址 2000 指针变量 指针变量 变量 变量地址(指针) 变量值 指向 地址存入

&与*运算符 两者关系:互为逆运算 理解 10 i_pointer &i &(*i_pointer) 含义: 取变量的地址 单目运算符 优先级: 2 结合性:自右向左 含义: 取指针所指向变量的内容 单目运算符 优先级: 2 结合性:自右向左 …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 指针变量 i_pointer &i &(*i_pointer) i *i_pointer *(&i) i_pointer = &i = &(*i_pointer) i = *i_pointer = *(&i) i_pointer-----指针变量,它的内容是地址量 *i_pointer----指针的目标变量,它的内容是数据 &i_pointer---指针变量占用内存的地址

2000 10 i_pointer *i_pointer &i_pointer i

直接访问与间接访问 直接访问:按变量地址存取变量值 间接访问:通过存放变量地址的变量去访问变量 例 i=3; -----直接访问 10 指针变量 …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 例 i=3; -----直接访问 20 3 例 *i_pointer=20; -----间接访问

例子图解 10 例 k=i; 例 k=i; --直接访问 k=*i_pointer; k=*i_pointer; --间接访问 10 指针变量 …... 2000 2004 2006 2005 整型变量i 10 变量i_pointer 2001 2002 2003 整型变量k 10

6.2 指针变量 指针变量与其所指向的变量之间的关系 指针变量的定义 一般形式: [存储类型] 数据类型 *指针名; 3 变量i 2000 i_pointer *i_pointer i &i i=3; *i_pointer=3 3 变量i 2000 i_pointer *i_pointer i &i i=3; *i_pointer=3 指针变量的定义 一般形式: [存储类型] 数据类型 *指针名; 例 int *p1,*p2; float *q ; static char *name; 表示定义指针变量 不是‘*’运算符 合法标识符 指针变量本身的存储类型 指针的目标变量的数据类型 注意: 1、int *p1, *p2; 与 int *p1, p2; 2、指针变量名是p1,p2 ,不是*p1,*p2 3、指针变量只能指向定义时所规定类型的变量 4、指针变量定义后,变量值不确定,应用前必须先赋值

指针变量的初始化 例 int i; 赋给指针变量, int *p=&i; 不是赋给目标变量 变量必须已说明过 类型应一致 例 int i; 一般形式:[存储类型] 数据类型 *指针名=初始地址值; 指针变量的初始化 例 int i; int *p=&i; 赋给指针变量, 不是赋给目标变量 变量必须已说明过 类型应一致 例 int i; int *p=&i; int *q=p; 例 int *p=&i; int i; 用已初始化指针变量作初值 例 main( ) { int i; static int *p=&i; .............. } () 不能用auto变量的地址 去初始化static型指针

指针变量必须先赋值,再使用 例 main( ) { int i=10; int *p; *p=i; printf(“%d”,*p); } …... 2000 2004 2006 2005 整型变量i 10 指针变量p 2001 2002 2003 随机 危险! 例 main( ) { int i=10,k; int *p; p=&k; *p=i; printf(“%d”,*p); }

零指针与空类型指针 零指针:(空指针) 定义:指针变量值为零 表示: int * p=0; p指向地址为0的单元, 系统保证该单元不作它用 表示指针变量值没有意义 #define NULL 0 int *p=NULL: 例 int *p; ...... while(p!=NULL) { ...… } 例 char *p1; void *p2; p1=(char *)p2; p2=(void *)p1; p=NULL与未对p赋值不同 用途: 避免指针变量的非法引用 在程序中常作为状态比较 表示不指定p是指向哪一种 类型数据的指针变量 void *类型指针 表示: void *p; 使用时要进行强制类型转换

printf("a=%d,b=%d\n",a,b); printf("max=%d,min=%d\n",*p1,*p2); } 例 输入两个数,并使其从大到小输出 main() { int *p1,*p2,*p,a,b; scanf("%d,%d",&a,&b); p1=&a; p2=&b; if(a<b) { p=p1; p1=p2; p2=p;} printf("a=%d,b=%d\n",a,b); printf("max=%d,min=%d\n",*p1,*p2); } …... 指针变量p1 指针变量p 2000 2008 2002 2004 2006 指针变量p2 整型变量b 整型变量a 2006 2008 2006 2008 2006 5 9 运行结果:a=5,b=9 max=9,min=5

指针变量作为函数参数——地址传递 特点:共享内存,“双向”传递 例 将数从大到小输出 swap(int x,int y) …... 2000 2008 200A 2002 2004 2006 变量a 变量b (main) swap(int x,int y) { int temp; temp=x; x=y; y=temp; } main() { int a,b; scanf("%d,%d",&a,&b); if(a<b) swap(a,b); printf("\n%d,%d\n",a,b); 5 5 9 9 变量temp 变量y 变量x (swap) COPY 9 5 5

特点:共享内存,“双向”传递 例 将数从大到小输出 swap(int x,int y) { int temp; 5 temp=x; x=y; 指针变量作为函数参数——地址传递 例 将数从大到小输出 …... 2000 2008 200A 2002 2004 2006 变量a 变量b (main) swap(int x,int y) { int temp; temp=x; x=y; y=temp; } main() { int a,b; scanf("%d,%d",&a,&b); if(a<b) swap(a,b); printf("\n%d,%d\n",a,b); 5 9 值传递 运行结果:5, 9

int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); 例 将数从大到小输出 swap(int *p1, int *p2) { int p; p=*p1; *p1=*p2; *p2=p; } main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b)swap(pointer_1,pointer_2); printf("\n%d,%d\n",a,b); …... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... 整型变量a 整型变量b (main) 指针pointer_1 指针pointer_2 9 5 5 9 2000 2000 2002 2002 COPY (swap) 指针p1 指针p2 整型p 5

int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); 例 将数从大到小输出(1) swap(int *p1, int *p2) { int p; p=*p1; *p1=*p2; *p2=p; } main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b)swap(pointer_1,pointer_2); printf("\n%d,%d\n",a,b); …... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... 整型变量a 整型变量b (main) 指针pointer_1 指针pointer_2 9 5 5 9 地址传递 2000 2002 运行结果:9,5

int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); 例 将数从大到小输出(2) …... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... swap(int *p1, int *p2) { int *p; *p=*p1; *p1=*p2; *p2=*p; } main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b) swap(pointer_1,pointer_2); printf("\n%d,%d\n",a,b); 整型变量a 整型变量b (main) 指针pointer_1 指针pointer_2 5 9 int x; int *p=&x;x; 9 9 2000 2000 2002 编译警告! 结果不对! 2002 COPY (swap) 指针p1 指针p2 指针p **** 假设2000 指针变量在使用前 必须赋值! 运行结果:9,9

int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); 例 将数从大到小输出(3) …... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... /*ch9_32.c*/ swap(int x,int y) { int t; t=x; x=y; y=t; } main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b) swap(*pointer_1,*pointer_2); printf("\n%d,%d\n",a,b); 整型a 整型b (main) pointer_1 pointer_2 5 值传递 9 2000 5 2002 9 COPY (swap) 整型x 整型b 整型t 9 5 5 运行结果:5,9

int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); 例 将数从大到小输出(4) swap(int *p1, int *p2) { int *p; p=p1; p1=p2; p2=p; } main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a; pointer_2=&b; if(a<b) swap(pointer_1,pointer_2); printf("%d,%d",*pointer_1,*pointer_2); …... 2000 2008 200A 2002 2004 2006 200C 200E 2010 ... 整型a 整型b (main) pointer_1 pointer_2 5 地址传递 9 2000 2000 2002 2002 COPY (swap) 指针p1 指针p2 指针p **** 2002 2000 2000 运行结果:5,9

指针变量和基类型 指针类型变量 这种变量的内容不再是常规意义上的数值,而是某个内存单元组的首地址定位和其占有字节数的多少,指针变量具有定位指向的控制能力。 基类型 把指针变量所控制的数据结构类型称为“基类型”。注意:指针值具有可列性,指针变量的自增或自减运算是以它基类型的字节数为数据单位 。

如 int i, *p; p=1000; () i=p; () 指针的运算 指针变量的赋值运算 p=&a; (将变量a地址p) p=array; (将数组array首地址p) p=&array[i]; (将数组元素地址p) p1=p2; (指针变量p2值p1) 不能把一个整数p,也不能把p的值整型变量 指针变量与其指向的变量具有相同数据类型

pi  p id (i为整型数,d为p指向的变量所占字节数) p++, p--, p+i, p-i, p+=i, p-=i等 指针的算术运算: pi  p id (i为整型数,d为p指向的变量所占字节数) p++, p--, p+i, p-i, p+=i, p-=i等 若p1与p2指向同一数组, p1-p2=两指针间元素个数(p1-p2)/d p1+p2 无意义 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a数组 p p+1,a+1 p+i,a+i p+9,a+9 1

例 p指向float数,则 p+1  p+1 4 例 p指向int型数组,且p=&a[0]; 则p+1 指向a[1] 例 int a[10]; int *p1=&a[2]; int *p2=&a[5]; 则:p2-p1=3; 例 int a[10]; int *p=&a[2]; p++; *p=1;

指针变量的关系运算 若p1和p2指向同一数组,则 p1<p2 表示p1指的元素在前 p1>p2 表示p1指的元素在后 p==NULL或p!=NULL

6.3 指针与数组 数组名是代表整个数组首地址的符号常量,若将数组名赋给基类型相同的指针变量,该指针变量就指向数组的首地址。 一维数组 它的基类型就是任一分量的数据类型(列指向); 二维数组 它的基类型可以是任一分量的数据类型(列指向),也可以用数组的“行”作为基类型(行指向)。

指向数组元素的指针变量 p array[0] array[1] 例 int array[10]; int *p; array[2] ... 整型指针p &array[0] p 例 int array[10]; int *p; p=&array[0]; // p=array; 或 int *p=&array[0]; 或 int *p=array; 数组名是表示数组首地址的地址常量

a[i]  p[i]  *(p+i) *(a+i) a[i]  *(a+i) a[0] a[1] a[2] a[3] a[9] ... a a+9 a+1 a+2 地址 元素 下标法 a[0] a[1] a[2] a[3] a[9] ... p p+9 p+1 p+2 地址 元素 指针法 *p *(p+1) *(p+2) *(p+9) *a *(a+1) *(a+2) *(a+9) p[0] p[1] p[2] p[9] a[i]  p[i]  *(p+i) *(a+i)

例 数组元素的引用方法 main() { int a[5],*pa,i; for(i=0;i<5;i++) a[i]=i+1; pa=a; printf("*(pa+%d):%d\n",i,*(pa+i)); printf("*(a+%d):%d\n",i,*(a+i)); printf("pa[%d]:%d\n",i,pa[i]); printf("a[%d]:%d\n",i,a[i]); } a[0] a[1] a[2] a[3] a[4] pa 1 2 3 4 5

 例 int a[]={1,2,3,4,5,6,7,8,9,10},*p=a,i; 数组元素地址的正确表示: (A)&(a+1) (B)a++ (C)&p (D)&p[i]  数组名是地址常量 p++,p-- () a++,a-- () a+1, *(a+2) ()

例 注意指针变量的运算 例 void main() { int a []={5,8,7,6,2,7,3}; int y,*p=&a[1]; 例 注意指针变量的运算 5 8 7 6 2 3 1 4 a p 6 例 void main() { int a []={5,8,7,6,2,7,3}; int y,*p=&a[1]; y=(*--p)++; printf(“%d”,y); } p 输出: 6

for(i=0;i<7;i++,p++) printf("%d",*p); } 例 注意指针的当前值 main() { int i,*p,a[7]; p=a; for(i=0;i<7;i++) scanf("%d",p++); printf("\n"); for(i=0;i<7;i++,p++) printf("%d",*p); } 5 8 7 6 2 3 1 4 a p p p p p p=a; p p p 指针变量可以指到数组后的内存单元

数组名作函数参数 数组名作函数参数,是地址传递 数组名作函数参数,实参与形参的对应关系 实参 形参 数组名 指针变量

例 将数组a中的n个整数按相反顺序存放 void inv(int *x, int n) 3 7 9 11 6 5 4 2 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] x p=x+m a数组 j i void inv(int *x, int n) { int t,*p,*i,*j,m=(n-1)/2; i=x; j=x+n-1; p=x+m; for(;i<=p;i++,j--) { t=*i; *i=*j; *j=t; } } main() { int i,a[10]={3,7,9,11,0,6,7,5,4,2}; inv(a,10); printf("The array has been reverted:\n"); for(i=0;i<10;i++) printf("%d,",a[i]); printf("\n"); } 2 3 i j 4 7 i j 5 9 i j 7 11 j i 6 实参用数组,形参用指针变量

一级指针变量与一维数组的关系 int *p 与 int q[10] 数组名是指针(地址)常量 p=q; p+i 是q[i]的地址 数组元素的表示方法:下标法和指针法, 即若p=q, 则 p[i]  q[i]  *(p+i)  *(q+i) 形参数组实质上是指针变量,即int q[ ]  int *q 在定义指针变量(不是形参)时,不能把int *p 写成int p[]; 系统只给p分配能保存一个指针值的内存区(一般2字节);而给q分配2*10字节的内存区

关于指针变量的运算 1、p++ (或p+=1) 使p指向下一个元素的地址。 2、若有*p++ 由于++ 和 * 同优先级,其结合方向为 main() { int a[8]={2,4,6,8,10,12,14,16}, i, *p; for(p=a, i=0; i<8; i++) printf(“%d,”, *p++); }

3、*(p++) 与 *(++p) 作用不同。 2 2 4 *(++p)与*++p 等价 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] 2 4 6 8 10 12 14 16 p *(p++) 2 p *(++p) 4 *(++p)与*++p 等价

4、(*p)++ 表示是 p 所指向的元素值加 1。 2 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] 2 4 6 8 10 12 14 16 3 p (*p)++

5、若有以下操作,则有: 2 *(p--) 5 3 *(++p) 6 *(--p) 3 4 6 8 10 12 14 16 p a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] *(p--) 5 2 4 6 8 10 12 14 16 3 *(++p) 6 p *(--p) 3

练习 若有以下定义,则其值为 3 的表达式是: int a[ ]={1,2,3,4,5,6,7,8}, *p; 1 2 3 4 5 6 7 p=a; a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] 1 2 3 4 5 6 7 8 p A) p+=2, *(p++) B) p+=2, *++p C) p+=3, *p++ D) p+=2, ++*p

练习 以下程序的输出结果是: main() { int a[ ]={1,2,3,4,5,6}, *p; 1 2 3 4 5 6 6 p=a; *(p+3)+=2; printf(“%d,%d\n”, *p, *(p+3)); } a[0] a[1] a[2] a[3] a[4] a[5] A) 0,5 B) 1,5 C) 0,6 D) 1,6 1 2 3 4 5 6 6 p

指针指向二维数组(数组指针) 二维数组的行是一种构造类型,若某指针指向它,就是“行指针”。行成为该指针所指的基类型,也是它的移动单位,定义数组指针的语法形式是: 类型名 (*指针变量名)[常量表达式]; 考察组合运算符( )[ ],属于同一优先级,自左向右,先处理圆括号,里面是指针变量,再处理右边的[ ],表示所指对象是个构造类型,元素个数由常量表达式决定,基类型是行,所以是行指针,行中的任一列元素的基类型由最前面的类型名给出。

二维数组的地址 指针与二维数组 对于一维数组: (1)数组名array表示数组的首地址,即array[0]的地址; int array[10]; 对于一维数组: (1)数组名array表示数组的首地址,即array[0]的地址; (2)数组名array是地址常量 (3)array+i是元素array[i]的地址 (4)array[i]  *(array+i)

int a[3][4]; 行指针与列指针(1) a a+1 a+2 *(a[0]+1) *(*(a+0)+1) 2000 2000 a[0] 2008 2016 a a+1 a+2 2000 2002 2008 2010 2016 2018 a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] a[0]+1 a[1]+1 a[2]+1 *(a+0)+1 *(a+1)+1 *(a+2)+1 对于二维数组: (1)a是数组名, 包含三个元素 a[0],a[1],a[2] (2)每个元素a[i] 又是一个一维 数组,包含4个 元素 基类型

行指针与列指针(2) 对二维数组 int a[3][4],有 a-----二维数组的首地址,即第0行的首地址 a+i-----第i行的首地址 a[i]  *(a+i)------第i行第0列的元素地址 a[i]+j  *(a+i)+j -----第i行第j列的元素地址 *(a[i]+j)  *(*(a+i)+j)  a[i][j] a+i=&a[i]=a[i]=*(a+i) =&a[i][0], 值相等,含义不同 a+i  &a[i],表示第i行首地址,指向行 a[i]  *(a+i)  &a[i][0],表示第i行第0列元素地址,指向列

int a[3][4]; a a+1 a+2 2000 a[0][0] a[0] 2002 a[0][1] a[0][2] a[0][3] 2008 2016 2002 2010 2018 a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] a a+1 a+2

*(a[1]+2),*(*(a+1)+2),a[1][2] 表格说明 表示形式 含义 地址 a 二维数组名,数组首地址 a[0],*(a+0),*a 第0行第0列元素地址 a+1 第1行首地址 a[1],*(a+1) 第1行第0列元素地址 a[1]+2,*(a+1)+2,&a[1][2] 第1行第2列元素地址 *(a[1]+2),*(*(a+1)+2),a[1][2] 第1行第2列元素值 2000 2008 2012 13

p 二维数组的指针变量 指向二维数组元素的指针变量 例 指向二维数组元素的指针变量 main() int a[3][4]; a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] p 例 指向二维数组元素的指针变量 main() { static int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int *p; for(p=a[0];p<a[0]+12;p++) { if((p-a[0])%4==0) printf("\n"); printf("%4d ",*p); }

a a+1 a+2 p p+1 p+2 p[0]+1或 *p+1 p[1]+2或 *(p+1)+2 p的值是一维数组的 首地址,p是行指针 定义形式: 数据类型 (*指针名)[一维数组维数]; 例 int (*p)[4]; 指向一维数组的指针变量 int a[3][4]; a[0][0] a[0][1] a[1][0] a[1][1] a[2][0] a[2][1] a[0][2] a[0][3] a[1][2] a[1][3] a[2][2] a[2][3] a a+1 a+2 p p+1 p+2 p[0]+1或 *p+1 p[1]+2或 *(p+1)+2 p的值是一维数组的 首地址,p是行指针 ( )不能少 int (*p)[4]与int *p[4]不同 *(*p+1)或 (*p)[1] *(*(p+1)+2) 可让p指向二维数组某一行 如 int a[3][4], (*p)[4]=a; 一维数组指针变量维数和 二维数组列数必须相同

printf("%d,%d\n",*((int *)p),*q); 例 二维数组与指针运算 main() { int a[3][4]={{1,2,3,4},{3,4,5,6},{5,6,7,8}}; int i; int (*p)[4]=a,*q=a[0]; for(i=0;i<3;i++) { if(i==0) (*p)[i+i/2]=*q+1; else p++,++q; } printf("%d,",a[i][i]); printf("%d,%d\n",*((int *)p),*q); p q p q p q 1 2 3 4 5 6 7 8 2 运行结果:2,4,7,5,3

6.4 指针与字符串 字符串表示形式 用字符数组实现 例 main( ) { char string[]=“I love China!”; \0 例 main( ) { char string[]=“I love China!”; printf(“%s\n”,string); printf(“%s\n”,string+7); }

字符指针初始化:把字符串首地址赋给string  char *string; string=“I love China!”; 用字符指针实现 I l o v e C h i string n ! a \0 字符指针初始化:把字符串首地址赋给string  char *string; string=“I love China!”; 例 main( ) { char *string=“I love China!”; printf(“%s\n”,string); string+=7; while(*string) { putchar(string[0]); string++; } string *string!=\0

void copy_string(char from[],char to[]) { int i=0; e c h \0 r . from b y u a r s t n d e to o . \0 字符串指针作函数参数 I a e c h \0 r . t m void copy_string(char from[],char to[]) { int i=0; while(from[i]!='\0') { to[i]=from[i]; i++; } to[i]='\0'; main() { char a[]="I am a teacher."; char b[]="You are a student."; printf("string_a=%s\n string_b=%s\n",a,b); copy_string(a,b); printf("\nstring_a=%s\nstring_b=%s\n",a,b); 例 用函数调用实现字符串复制 void copy_string(char *from,char *to) { for(;*from!='\0';from++,to++) *to=*from; *to='\0'; } main() { char *a="I am a teacher."; char *b="You are a student."; printf("string_a=%s\nstring_b=%s\n",a,b); copy_string(a,b); printf("\nstring_a=%s\nstring_b=%s\n",a,b); (1)用字符数组作参数 (2)用字符指针变量作参数

char *cp; 与 char str[20]; str由若干元素组成,每个元素放一个字符;而cp中存放字符串首地址 char str[20]; str=“I love China!”; () char *cp; cp=“I love China!”; () str是地址常量;cp是地址变量 cp接受键入字符串时,必须先开辟存储空间 字符指针变量与字符数组 例 char str[10]; scanf(“%s”,str); () 而 char *cp; scanf(“%s”, cp); () 改为: char *cp,str[10]; cp=str; scanf(“%s”,cp); ()

字符串与数组关系 字符串用一维字符数组存放 字符数组具有一维数组的所有特点 数组名是指向数组首地址的地址常量 数组元素的引用方法可用指针法和下标法 数组名作函数参数是地址传递等 区别 存储格式:字符串结束标志 赋值方式与初始化 输入输出方式:%s %c scanf(“%s”,str); printf(“%s”,str); gets(str); puts(str); char str[]={“Hello!”}; () char str[]=“Hello!”; () char str[]={‘H’,‘e’,‘l’,‘l’,‘o’,‘!’}; () char *cp=“Hello”; () int a[]={1,2,3,4,5}; () int *p={1,2,3,4,5}; () char str[10],*cp; int a[10],*p; str=“Hello”; () cp=“Hello!”; () a={1,2,3,4,5}; () p={1,2,3,4,5}; ()

6.5 指针与函数 函数指针:函数在编译时被分配的入口地址,用函数名表示 指向函数的指针变量 定义形式: 数据类型 (*指针变量名)(); 6.5 指针与函数 函数指针:函数在编译时被分配的入口地址,用函数名表示 max …... 指令1 指令2 指向函数的指针变量 定义形式: 数据类型 (*指针变量名)(); 如 int (*p)(); 函数指针变量赋值:如p=max; ( )不能省 int (*p)() 与 int *p()不同 专门存放函数入口地址 可指向返回值类型相同的不同函数 函数返回值的数据类型 函数调用形式: c=max(a,b);  c=(*p)(a,b);  c=p (a,b); 对函数指针变量pn, p++, p--无意义 函数指针变量指向的函数必须有函数说明

用函数指针变量作函数参数 例 用函数指针变量作参数,求最大值、最小值和两数之和 void main() { int a,b,max(int,int), min(int,int),add(int,int); void process(int,int,int (*fun)()); scanf("%d,%d",&a,&b); process(a,b,max); process(a,b,min); process(a,b,add); } prvoidocess(int x,int y,int (*fun)()) { int result; result=(*fun)(x,y); printf("%d\n",result); max(int x,int y) { printf(“max=”); return(x>y?x:y); min(int x,int y) { printf(“min=”); return(x<y?x:y); add(int x,int y) { printf(“sum=”); return(x+y);

float *search(float (*pointer)[4],int n), *p; int i,m; 8.6 返回指针值的函数 main() { float score[][4]={{60,70,80,90}, {56,89,67,88},{34,78,90,66}}; float *search(float (*pointer)[4],int n), *p; int i,m; printf("Enter the number of student:"); scanf("%d",&m); printf("The scores of No.%d are:\n",m); p=search(score,m); for(i=0;i<4;i++) printf("%5.2f\t",*(p+i)); } float *search(float (*pointer)[4], int n) { float *pt; pt=*(pointer+n); return(pt); 函数定义形式: 类型标识符 *函数名(参数表); 例 int *f(int x, int y) 例 指针函数实现:有若干学生成绩,要求输入学生序号后, 能输出其全部成绩 p p p p pointer pointer+1 34 78 90 66 56 89 67 88 60 70 80 score数组

例 写一个函数,求两个int型变量中居于较大值的变量的地址(1) int *f1(int *x,int *y) { if(*x>*y) return x; else return y; } main() { int a=2,b=3; int *p; p=f1(&a, &b); printf("%d\n",*p); …... 2000 2008 200A 2002 2004 2006 变量a 变量b (main) 指针变量p COPY 2 3 ** 指针变量y 指针变量x (f1) 2000 2002

例 写一个函数,求两个int型变量中居于较大值的变量的地址(2) int *f3(int *x,int *y) { if(*x>*y) return x; else return y; } main() { int a=2,b=3; int *p; p=f1(&a,&b); printf("%d\n",*p); …... 2000 2008 200A 2002 2004 2006 2 变量a 变量b (main) 3 指针变量p ** 2002

例 写一个函数,求两个int型变量中居于较大值的变量的地址(3) int *f3(int x,int y) { if(x>y) return &x; else return &y; } main() { int a=2,b=3; int *p; p=f3(a, b); printf("%d\n",*p); …... 2000 2008 200A 2002 2004 2006 变量a 变量b (main) 指针变量p COPY 2 3 ** 变量y 变量x (f3) 2 3

例 写一个函数,求两个int型变量中居于较大值的变量的地址(4) int *f3(int x,int y) { if(x>y) return &x; else return &y; } main() { int a=2,b=3; int *p; p=f3(a,b); printf("%d\n",*p); …... 2000 2008 200A 2002 2004 2006 2 变量a 变量b (main) 3 指针变量p ** 200A 不能返回形参或局部变量 的地址作函数返回值

指针数组和多级指针 用于处理二维数组或多个字符串 指针数组 指针数组赋值与初始化 指针本身的存储类型 指针所指向变量的数据类型 赋值: 定义:数组中的元素为指针变量 定义形式:[存储类型] 数据类型 *数组名[数组长度说明]; 例 int *p[4]; 指针数组赋值与初始化 指针本身的存储类型 指针所指向变量的数据类型 赋值: main() { int b[2][3],*pb[2]; pb[0]=b[0]; pb[1]=b[1]; …….. } int *pb[2] pb[0] pb[1] int b[2][3] 1 2 3 4 6 区分int *p[4]与int (*p)[4] 初始化: main() { int b[2][3],*pb[ ]={b[0],b[1]}; …….. } int *pb[2] pb[0] pb[1] int b[2][3] 1 2 3 4 6

p[0]=a; p[1]=b; p[2]=c; p[3]=NULL; …….. } 或: { char *p[4]; 指针数组赋值与初始化 L i s p \0 F o r t r a n \0 B a s i c \0 p[0] p[1] p[2] p[3] 赋值: main() { char a[]="Fortran"; char b[]="Lisp"; char c[]="Basic"; char *p[4]; p[0]=a; p[1]=b; p[2]=c; p[3]=NULL; …….. } 或: { char *p[4]; p[0]= "Fortran"; p[1]= "Lisp"; p[2]= "Basic"; p[3]=NULL; 初始化: main() { char *p[]={"Fortran", "Lisp", "Basic",NULL}; …….. } L i s p \0 F o r t r a n \0 B a s i c \0 p[0] p[1] p[2] p[3]

二维数组与指针数组区别: 指针数组元素的作用相当于二维数组的行名 二维数组存储空间固定 但指针数组中元素是指针变量 char name[5][9]={“gain”,“much”,“stronger”, “point”,“bye”}; g a i n \0 s t r o n g e r \0 p o i n t \0 m u c h \0 name[0] name[1] name[2] name[3] name[4] b y e \0 g a i n \0 s t r o n g e r \0 p o i n t \0 m u c h \0 b y e \0 char *name[5]={“gain”,“much”,“stronger”, “point”,“bye”}; 二维数组存储空间固定 字符指针数组相当于可变列长的二维数组 分配内存单元=数组维数*2+各字符串长度 指针数组元素的作用相当于二维数组的行名 但指针数组中元素是指针变量 二维数组的行名是地址常量

for(j=0;j<3;j++,pb[i]++) printf("b[%d][%d]:%2d\n",i,j,*pb[i]); } 例 用指针数组处理二维数组 main() { int b[2][3],*pb[2]; int i,j; for(i=0;i<2;i++) for(j=0;j<3;j++) b[i][j]=(i+1)*(j+1); pb[0]=b[0]; pb[1]=b[1]; for(j=0;j<3;j++,pb[i]++) printf("b[%d][%d]:%2d\n",i,j,*pb[i]); } int *pb[2] pb[0] pb[1] int b[2][3] 1 2 3 4 6 b[0][0] *pb[0] b[0][1] *(pb[0]+1) b[0][2] *(pb[0]+2) b[1][0] *pb[1] b[1][1] *(pb[1]+1) b[1][2] *(pb[1]+2)

k k j j j j i=0 例 对字符串排序(简单选择排序)图解1 main() 例 对字符串排序(简单选择排序)图解1 main() { void sort(char *name[],int n), print(char *name[],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer "}; int n=5; sort(name,n); print(name,n); } void sort(char *name[],int n) { char *temp; int i,j,k; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} name[0] name[1] name[2] name[3] name[4] name Great Wall FORTRAN Computer Follow me BASIC k k j j j j i=0

例 对字符串排序(简单选择排序)图解2 k j k j k j i=1 main() 例 对字符串排序(简单选择排序)图解2 main() { void sort(char *name[],int n), print(char *name[],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer "}; int n=5; sort(name,n); print(name,n); } void sort(char *name[],int n) { char *temp; int i,j,k; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} name name[0] Follow me k name[1] BASIC j name[2] Great Wall k j name[3] FORTRAN k j name[4] Computer i=1

k k j j i=2 例 对字符串排序(简单选择排序)图解3 main() 例 对字符串排序(简单选择排序)图解3 main() { void sort(char *name[],int n), print(char *name[],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer "}; int n=5; sort(name,n); print(name,n); } void sort(char *name[],int n) { char *temp; int i,j,k; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} name name[0] Follow me name[1] BASIC k name[2] Great Wall k j name[3] FORTRAN j name[4] Computer i=2

例 对字符串排序(简单选择排序)图解4 k k j i=3 main() 例 对字符串排序(简单选择排序)图解4 main() { void sort(char *name[],int n), print(char *name[],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer "}; int n=5; sort(name,n); print(name,n); } void sort(char *name[],int n) { char *temp; int i,j,k; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} name name[0] Follow me name[1] BASIC name[2] Great Wall k name[3] FORTRAN k j name[4] Computer i=3

例 对字符串排序(简单选择排序)图解5 main() 例 对字符串排序(简单选择排序)图解5 main() { void sort(char *name[],int n), print(char *name[],int n); char *name[]={"Follow me","BASIC", "Great Wall","FORTRAN","Computer "}; int n=5; sort(name,n); print(name,n); } void sort(char *name[],int n) { char *temp; int i,j,k; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0) k=j; if(k!=i) { temp=name[i]; name[i]=name[k]; name[k]=temp;} name name[0] Follow me name[1] BASIC name[2] Great Wall name[3] FORTRAN name[4] Computer

多级指针 定义: 指向指针的指针 一级指针:指针变量中存放目标变量的地址 例 int *p; int i=3; p=&i; *p=5; 单级间接寻址 二级指针:指针变量中存放一级指针变量的地址 例 int **p1; int *p2; int i=3; p2=&i; p1=&p2; **p1=5; p1 &p2 &i 3 P2(指针变量) i(整型变量) 二级指针 一级指针 目标变量 二级间接寻址

多级指针定义形式 定义形式:[存储类型] 数据类型 **指针名; 如 char **p; *p是p间接指向对象的地址 定义形式:[存储类型] 数据类型 **指针名; 如 char **p; *p是p间接指向对象的地址 **p是p间接指向对象的值 指针本身的存储类型 最终目标变量的数据类型 例 int i=3; int *p1; int **p2; p1=&i; p2=&p1; **p=5; i p1 p2 3 &i &p1 **p2, *p1 *p2 例 int i, **p; p=&i; ()//p是二级指针,不能用变量地址为其赋值 多级指针 例 三级指针 int ***p; 四级指针 char ****p;

#include <stdio.h> void swap(int *r,int *s) { int *t; t=r; r=s; 例 一级指针与二级指针图解1 #include <stdio.h> void swap(int *r,int *s) { int *t; t=r; r=s; s=t; } main() { int a=1,b=2,*p,*q; p=&a; q=&b; swap(p,q); printf("%d,%d\n",*p,*q); 2000 2008 200A 2002 2004 2006 1 2 变量a 变量b (main) 指针变量p 指针变量q COPY 指针变量s 指针变量r (swap) 指针变量t 2002 2000 2002 2000 2000

#include <stdio.h> void swap(int *r,int *s) { int *t; t=r; r=s; 例 一级指针与二级指针图解2 #include <stdio.h> void swap(int *r,int *s) { int *t; t=r; r=s; s=t; } main() { int a=1,b=2,*p,*q; p=&a; q=&b; swap(p,q); printf("%d,%d\n",*p,*q); 2000 2008 200A 2002 2004 2006 1 2 变量a 变量b (main) 指针变量p 指针变量q 输出: 1,2

#include <stdio.h> void swap(int *r,int *s) { int *t; t=r; r=s; 例 一级指针与二级指针图解3 a b p q #include <stdio.h> void swap(int *r,int *s) { int *t; t=r; r=s; s=t; } main() { int a=1,b=2,*p,*q; p=&a; q=&b; swap(p,q); printf("%d,%d\n",*p,*q); a b p q r s a b p q s r a b p q 输出: 1,2

#include <stdio.h> void swap(int **r,int **s) { int *t; t=*r; 例 一级指针与二级指针图解4 #include <stdio.h> void swap(int **r,int **s) { int *t; t=*r; *r=*s; *s=t; } main() { int a=1,b=2,*p,*q; p=&a; q=&b; swap(&p,&q); printf("%d,%d\n",*p,*q); 2000 2008 200A 2002 2004 2006 1 2 变量a 变量b (main) 指针变量p 指针变量q 2002 COPY 2000 二级指针s 二级指针r (swap) 指针变量t 2006 2004 2000

#include <stdio.h> void swap(int **r,int **s) { int *t; t=*r; 例 一级指针与二级指针图解5 #include <stdio.h> void swap(int **r,int **s) { int *t; t=*r; *r=*s; *s=t; } main() { int a=1,b=2,*p,*q; p=&a; q=&b; swap(&p,&q); printf("%d,%d\n",*p,*q); 2000 2008 200A 2002 2004 2006 1 2 变量a 变量b (main) 指针变量p 指针变量q 2002 2000 输出: 2,1

#include <stdio.h> void swap(int **r,int **s) { int *t; t=*r; 例 一级指针与二级指针图解6 a b p q #include <stdio.h> void swap(int **r,int **s) { int *t; t=*r; *r=*s; *s=t; } main() { int a=1,b=2,*p,*q; p=&a; q=&b; swap(&p,&q); printf("%d,%d\n",*p,*q); a b r s p q a b r s p q b a p q 输出: 2,1

C:\TC> copy[.exe] source.c temp.c 命令行参数 命令行:在操作系统状态下,为执行某个程序而键入的一行字符 命令行一般形式:命令名 参数1 参数2………参数n C:\TC> copy[.exe] source.c temp.c 带参数的main函数形式: 有3个字符串参数的命令行 main(int argc, char *argv[]) { ……… } 命令行参数传递 命令行实参 main(形参) 系统自动调用 main函数时传递 命令行中参数个数 形参名任意 元素指向命令行参数 中各字符串首地址 第一个参数: main所在的可执行文件名

n个指向整型数据的指针变量组成的指针数组p 定义 含义 int i; int *p; int a[n]; int *p[n]; int (*p)[n]; int f(); int *p(); int (*p)(); int **p; 定义整型变量i p为指向整型数据的指针变量 定义含n个元素的整型数组a n个指向整型数据的指针变量组成的指针数组p p为指向含n个元素的一维整型数组的指针变量 f为返回整型数的函数 p为返回指针的函数,该指针指向一个整型数据 p为指向函数的指针变量,该函数返回整型数 p为指针变量,它指向一个指向整型数据的指针变量 指针的数据类型