第八章 指 针 8.1 指针的概念与定义 8.2 指针作函数参数 8.3 指针与数组 8.4 指针与函数 8.5 复杂指针.

Slides:



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

第七章 指针 计算机公共教学部.
第六章 指针 指针的概念 指针变量 指针与数组 指针与函数 返回指针值的函数.
第十章 指针 分析C程序的变量所存放的数据:  数值型数据:整数、实数  字符型数据:字符、字符串 这些变量具有以下性质:
第7章 指针 存储地址的变量的类型就是指针类型 能直接对内存地址操作, 实现动态存储管理 容易产生副作用, 初学者常会出错
电子成绩单项目实现.
二级指针与二维数组.
C语言程序设计基础 第10章 指针进阶 刘新国.
10.1 二级指针 10.2 指针与二维数组 10.3 指针的动态存储分配 10.4 函数指针 10.5 main函数的参数
第 6 章 第 6 章 指 针 指 针 1.
C语言基础——指针的高级应用 Week 05.
第6章 指针 6.1 指针的概念 6.2 变量与指针 6.3 数组与指针 6.4 字符串与指针 6.5 函数与指针 6.6 返回指针值的函数
6.4 字符串与指针 1. 用字符数组存放一个字符串.
第六节 二维数组和指针 二维数组的地址 对于一维数组: (1)数组名array表示数组的首地址, 即array[0]的地址;
第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
第6章 指针 学习目的与要求: 了解指针的概念和相关术语 熟练掌握指向变量、数组和字符串的指针变量的使用方法 了解指向函数的指针变量
指 针 为什么要使用指针 指针变量 指针与数组 返回指针值的函数 动态内存分配 通过指针引用字符串 指向函数的指针 小 结 习 题.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
Introduction to the C Programming Language
目录 10.1 指针的基本概念 10.2 指向变量的指针变量 10.3 指向数组的指针变量 10.4 指向函数的指针变量和指针型函数
第 十 章 指 针.
项目六 用指针优化学生成绩排名 项目要求 项目分析
C语言高级编程(第四部分) 字符串 北京大学 信息科学技术学院.
Chap 2 用C语言编写程序 2.1 在屏幕上显示 Hello World! 2.2 求华氏温度 100°F 对应的摄氏温度
目录 第八章 数组 1 简单学生成绩管理系统的开发 2 一维数组 3 多维数组 4 字符数组 5 数组作函数参数.
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
计算概论 第十八讲 C语言高级编程 结构与习题课 北京大学信息学院.
Introduction to the C Programming Language
Function.
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
Chap 8 指针 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 指向函数的指针
二维数组的指针表示 与复杂的指针例子 专题研讨课之三.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
C语言 程序设计基础与试验 刘新国、2012年秋.
C语言程序设计基础 第8章 指针 刘新国.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
第8章 指针.
第八章 使用指针.
第十章 指针.
欲穷千里,更上层楼 第十章 指 针 指针是C语言中广泛使用的一种数据类型。 运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构; 能很方便地使用数组和字符串; 并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。指针极大地丰富了C语言的功能。 学习指针是学习C语言中最重要的一环,
第五章 习题课 电子信息与计算机科学系 曾庆尚.
第七章 函数及变量存贮类型 7.1 函数基础与C程序结构 7.2 函数的定义和声明 7.3 函数的调用 7.4 函数的嵌套与递归
9.1 地址、指针和变量 9.2 指针运算 9.3 指针与数组 9.4 函数与指针 9.5 程序综合举例 9.6 上机实训.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C语言复习3----指针.
C语言大学实用教程 第7章 指针 西南财经大学经济信息工程学院 刘家芬
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
第6讲 指针与引用 6.1 指针 6.2 引用.
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第十四章 若干深入问题和C独有的特性 作业: 函数指针 函数作参数 函数副作用 运算 语句 位段 存储类别 编译预处理
第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。
C程序设计.
第4章 Excel电子表格制作软件 4.4 函数(一).
C程序设计.
第九章 指针.
第九节 赋值运算符和赋值表达式.
第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语言程序设计 第8章 指针.
Chap 7 数 组 7.1 排序问题 7.2 找出矩阵中最大值所在的位置 7.3 进制转换.
Introduction to the C Programming Language
第九章 指针 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第八章 指 针 北京邮电大学出版社.
第7章 地址和指针 7.1 地址和指针的概念 7.2 指针变量的定义和指针变量的基类型 7.3 给指针变量赋值 7.4 对指针变量的操作
Presentation transcript:

第八章 指 针 8.1 指针的概念与定义 8.2 指针作函数参数 8.3 指针与数组 8.4 指针与函数 8.5 复杂指针

8.1 指针的概念与定义 8.1.1 指针的概念 图 8.1 内存分配表

8.1.2 指针的定义及使用 1. 指针的定义 指针是一种存放地址值的变量,像其它变量一样,必须在使用前定义。指针变量的命名遵守与其它变量相同的规则, 即必须是唯一的标识符。指针定义的格式如下:  类型名 *指针名;

例 8.1 指针与非指针的定义 例 8.2 指针的指向 int *point;  scanf("%d", point); 例 8.1 指针与非指针的定义 char *pcl,*pc2; /* pcl和pc2均为指向char型的指针*/ float *pf, percent;/* pf是float型的指针,而percent为普通的float型变量*/ 例 8.2 指针的指向 int *point;  scanf("%d", point);

2. 指针的有关运算符 两个有关的运算符:  &: 取地址运算符。  *: 指针运算符(或称“间接访问”运算符)。  例如:&a为变量a的地址, *p为指针p所指向的存贮单元的内容。  &运算符只能作用于变量,包括基本类型变量和数组的元素、 结构体类型变量或结构体的成员(第九章), 不能作用于数组名、 常量或寄存器变量。 例如:

表达式&r、 &a[0]、 &a[i]是正确的, 而&(2*r)、 &a、&k是非法表示。 double r, a[20];  int i;  register int k; 表达式&r、 &a[0]、 &a[i]是正确的, 而&(2*r)、 &a、&k是非法表示。 单目运算符*是&的逆运算,它的操作数是对象的地址, *运算的结果是对象本身。 单目*称为间访运算符,“间访”就是通过变量的地址而不是变量名存取(或引用)变量。例如, 如果pc是指向字符变量c的指针,则*(&c)和*pc表示同一字符对象c。因而赋值语句 *(&c)=′a′;  *pc=′a′;  c=′a′; 效果相同,都是将′a′存入变量c。

例 8.3 取地址运算符。 int variable, *point;  point=&variable;

3. 指针的使用 例 8.4 指针的使用。 main( ) {int a, b, *p1, *p2;  a=10; b=20;  例 8.4 指针的使用。 main( ) {int a, b, *p1, *p2;  a=10; b=20;  p1=&a; p2=&b;  printf("%d\t%d\n", *p1, *p2);  p1=&b; p2=&a;  } 程序运行结果:  10 20 20 10

程序说明:  (1) 在两个printf函数调用语句中的*是指针运算符,这一单目运算符的运算对象应该是指针或地址, 它的作用是得到指针指向变量的值。  (2) 在第一个printf函数调用时, 可以假设内存的分配如图8.2所示。 图 8.2 内存分配表

(3) 在第二个printf函数调用时,内存的分配将如图8.3所示。 图 8.3 内存分配表

例 8.5 指针的使用。 程序运行结果:  10 20.5 10 20.5 main( ) {int a, *pi;  例 8.5 指针的使用。 main( ) {int a, *pi;  float f, *pf;  a=10; f=20.5;  pi=&a; pf=&f;  printf("%d\t%4.1f\n", a, f);  printf("%d\t%4.1f\n", *pi, *pf);  } 程序运行结果:  10 20.5 10 20.5

程序说明: 图 8.4 内存分配表

8.2 指针作函数参数 例 8.6 函数参数的传递。 void swap(int x, int y);  main() {  8.2 指针作函数参数 例 8.6 函数参数的传递。 void swap(int x, int y);  main() {  int a, b;  a=10; b=20;  swap(a, b);  printf("a=%d, b=%d\n", a, b);  }

void swap(int x, int y) 运行结果:  a=10, b=20 { int temp;  temp=x;  x=y;  y=temp;  } 运行结果:  a=10, b=20

图 8.5 swap函数被调用时的内存分配图 图 8.6 swap函数调用结束时的内存分配图

例 8.7 指针作函数参数。 void swap(int * x, int * y);  main() { 例 8.7 指针作函数参数。 void swap(int * x, int * y);  main() { int a, b, *p1, *p2;  a=10; b=20; p1=&a; p2=&b;  swap(p1, p2);  printf("a=%d, b=%d\n", a, b); /* 或printf(″%d %d″, *p1, *p2) */ } void swap(int *pa, int *pb) int temp;  temp=*pa;  *pa=*pb;  *pb=temp;  } 运行结果:  a=20, b=10

图 8.7 swap函数被调用时的内存分配图 图 8.8 swap函数调用结束时的内存分配图

例 8.8 指针作函数参数。 void swap(int *, int *);  main() {  例 8.8 指针作函数参数。 void swap(int *, int *);  main() {  int a, b, *p1, *p2;  a=10; b=20; p1=&a; p2=&b;  swap(p1, p2);  printf("a=%d, b=%d\n", a, b);  } void swap(int *pa, int *pb) int *temp;  temp=pa;  pa=pb;  pb=temp;  运行结果:  a=10, b=20

图 8.9 swap函数被调用时的内存分配图 图 8.10 swap函数调用结束时的内存分配图

例 8.9 指针作函数参数。 void swap(int *, int *); main() {  例 8.9 指针作函数参数。 void swap(int *, int *); main() {  int a, b, *p1, *p2;  a=10; b=20; p1=&a; p2=&b;  swap(p1, p2);  printf("a=%d, b=%d\n", a, b);  } void swap(int *pa, int *pb) int *temp;  *temp=*pa;  *pa=*pb;  *pb=*temp;  }

可以将swap函数改变成这样: void swap(int *pa, int *pb) { int *temp, t;  *temp=*pa;  *pa=*pb;  *pb=*temp;  } 此时可以得到运行结果:  a=20, b=10

8.3 指 针 与 数 组 8.3.1 指向一维数组的指针 图 8.11 指向数组元素的指针

实际上,C语言允许这样的表达方式: pa[i]和. (a+i), 它们等价于 实际上,C语言允许这样的表达方式: pa[i]和*(a+i), 它们等价于*(pa+i)和a[i]。由此可见,引用数组元素有两种等价的形式: 通过下标引用和通过指针引用。以数组a为例, 假定pa指向a[0],元素的下标引用和指针引用的对应关系如下(写在同一行上的表达式是对同一元素的等价引用形式): a[0] *pa *a或*(a+0) a[1] *(pa+1) *(a+1) a[2] *(pa+2) *(a+2) … … … a[9] *(pa+9) *(a+9)

元素地址的对应关系如下:  &a[0] pa a或a+0 &a[1] pa+1 a+1 &a[2] pa+2 a+2 … … … &a[9] pa+9 a+9

8.3.2 数组作函数参数 例 8.10 数组名作函数参数 main() { int *p, i, a[10];  p=a;  8.3.2 数组作函数参数 例 8.10 数组名作函数参数 main() { int *p, i, a[10];  p=a;  for(i=0; i<10; i++) scanf("%d", p++);  sort(p, 10);  for(p=a, i=0; i<10; i++)

{ printf("%5d", *p); p++; } printf("\n");  } sort(int x[], int n) { int i, j, k, t;  for(i=0; i<n-1; i++) { k=i;  for(j=i+1; j<n; j++) if(x[j]>x[k]) k=j;  if(k!=i) { t=x[i]; x[i]=x[k]; x[k]=t; }

函数sort的形参x可以认为是main函数中数组a的别名, 所以在函数sort中对x的操作就是对a的操作,使得数组a得以排序, 完成了程序的要求。注意在main函数中使用指针p时,指针当前指向的变化。当然,main函数中调用sort函数时实参可以是指针,也可以是数组名,在函数sort中形参可以是数组名, 也可以是指针。 可将上例的程序改写如下: main() { int i, a[10];  for(i=0; i<10; i++) scanf("%d", &a[i]);  sort(a, 10); 

printf("%5d", a[i]);  } sort(int *x, int n) { int i, j, k, t;  for(i=0; i<n-1; i++) {k=i;  for(j=i+1; j<n; j++) if(x[j]>x[k]) k=j;  if(k!=i) { t=x[i]; x[i]=x[k]; x[k]=t;  }

8.3.3 指针和字符串 在C语言中,字符串(例如"I am a student")指在内存中存放的一串以′\0′结尾的若干个字符。例如,可以这样定义和初始化一个字符数组:  char string[]="I am a student";  数组长度由字符串长度加1确定。也可以定义一个字符数组, 然后用标准输入函数从外部设备读入一个字符串。例如:  char string[20];  scanf("%s", string);

数组长度应能足够存放读入的最大长度的字符串。  利用指针也可以表达字符串, 而且比用字符数组更为方便灵活。例如,可以这样定义和初始化一个字符指针:  char *point="I am a student";  point是指向字符串"I am a student"的指针,即字符串的首地址赋给了字符指针,因此使一个字符指针指向一个字符串。 也可以采用下面的方式:  char *point;  point="I am a student";

例 8.11 字符串拷贝函数。 #include<stdio.h> void my-strcpy(char *t, char *s) 例 8.11 字符串拷贝函数。 #include<stdio.h> void my-strcpy(char *t, char *s) {  while((*t=*s)!=′\0′) { s++;  t++;  } }

下列对my-strcpy函数的调用都是正确的: (1)my-strcpy(s1,"I am a student");  (2) ps1=&s1[0];  ps2="I am a student";  my-strcpy(ps1, ps2);  (3) ps2=&s2[0];  my-strcpy(ps2,"I am a student");  my-strcpy(s1,s2); 或 my-strcpy(s1,ps2);

my-strcpy的定义可以写成更简练的形式;  void my-strcpy(char *t, char *s) {  while((*t++=*s++)!=′\0′);  } 复制过程继续的条件是被复制的字符为非0(非′\0′)。 由于组成字符串的任何字符(′\0′除外)的值都为非0, 所以my-strcpy还可以进一步简化为  void my-strcpy(char *t, char *s) while(*t++=*s++);  }

例 8.12 字符串比较函数。 int my-strcmp(char *s, char *t) {  例 8.12 字符串比较函数。 int my-strcmp(char *s, char *t) {  for(; *s==*t; s++, t++) if(*s==′\0′) return 0;  return(*s-*t);  }

8.3.4 指向多维数组的指针 设有一个二维数组的定义为 static int a[2][4]={{1, 3, 5, 7}, {2, 4, 6, 8}}; 我们可以假设数组a在内存中的分配情况如下:

详细区分说明如下:

例 8.13 多维数组。 运行结果:  1 3 5 7 2 4 6 8 10 20 30 40 main() {  例 8.13 多维数组。 main() {  static int a[3][4]={{1, 3, 5, 7}, {2, 4, 6, 8}, {10, 20, 30, 40}};  int *p;  for(p=a[0]; p<a[0]+12; p++) /* 注1 */ { if((p-a[0])%4==0) printf("\n"); /* 注2 */ printf("%4d", *p);  } } 运行结果:  1 3 5 7 2 4 6 8 10 20 30 40

例 8.14 多维数组。 运行结果: 1 3 5 7 2 4 6 8 10 20 30 40 main() {  例 8.14 多维数组。 main() {  static int a[3][4]={{1, 3, 5, 7}, {2, 4, 6, 8}, {10, 20, 30, 40}};  int i, j, (*p)[4];  p=a;  for(i=0; i<3; i++) { for(j=0; j<4; j++) printf("%4d", *(*(p+i)+j));  printf("\n");  } } 运行结果: 1 3 5 7 2 4 6 8 10 20 30 40

(1) 形参说明为指向数组元素的指针, 实参为数组元素的地址或指向元素的指针。  例如:  调用函数f, 用数组元素的地址作实参: int a[2][3];  void f(int *, int);  … f(a[0], 2*3);  …

调用函数f,用指向数组元素的指针作实参: int a[2][3], *pi;  void f(int *, int);  … pi=a[0]; /* 或pi=&a[0][0] */ f(pi, 2*3);  … pi是指向元素 a[0][0]的指针。  函数f的定义: 〖HT5”〗 void f(int *pi, int size) { } 形参pi说明为列指针。

(2) 形参说明为行指针, 实参为行地址或行指针。例如, 调用函数f, 用行指针作实参:  { int a[2][3];  void f(int (*)[3], int);  … f(a, 2);  }

实参 a是行指针,类型为 int(*)[3];实参 2是二维数组 a的行数。  调用函数f, 用行指针作实参:  int a[2][3], (*pa)[3];  void f(int(*)[3], int); … pa=a;  f(pa, 2);  …

pa是行指针,赋值语句“pa=a; ”使pa指向a的第0行, pa的类型与a的类型相同。  函数f的定义:  void f(int (*pa)[3], int size) {  … }

例 8.15 行指针作函数参数 输入一个用年、月、日表示的日期,定义函数day- of-year将它转换成该年的第几天;输入某年的第几天,定义函数 month-day将它转换成该年的某月某日。 #include<stdio.h> /* day-of-year: 从月份和日期计算为一年中的第几天 */ int day-of-year(int year, int month, int day, int *pi) {  int i, leap;  leap=year%4==0&&year%100![KG-*4]=0||year%400==0;  for(i=1; i<month; i++) day+=*(pi+leap*13+i);  return (day);  }

/* month-day: 从一年中的第几天计算月份和日期 */ void month-day(int year, int yday, int (*pdaytab)[13], int *pmonth, int pday) {  int i, leap;  leap=year%4==0&&year%100![KG-*4]=0||year%400==0;  for(i=1; yday>*(*(pdaytab+leap)+i); i++) yday-=*(*(pdaytab+leap)+i);  *pmonth=i;  *pday=yday;  } int main(void) {

int daytab[2][13]={ {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},  {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }, y, m, d, yd;  printf("input year, month, day: \n");  scanf("%d%d%d", &y, &m, &d);  yd=day-of-year(y, m, d, &daytab[0][0]);  printf("day of year is %d\n", yd);  printf("input year, day-of-year: \n");  scanf("%d%d", &y, &yd); 

month-day(y, yd, daytab, &m, &d);  printf("%d, %d in %d\n", m, d, y);  return 0;  } input year, month, day: (输出)  1995 12 11  (输入) day of year is 345 (输出) input year, day-of-year: (输出) 1994 280 (输入) 10, 7 in 1994 (输出)

8.3.5 指针数组 指针变量可以同其它变量一样作为数组的元素, 由指针变量组成的数组称为指针数组,组成数组的每个元素都是相同类型的指针。  指针数组说明的形式为 类型名 *数组名[常量表达式]:  其中“*数组名[常量表达式]”是指针数组说明符。 例如: int *ps[10];

设有二维数组说明:  int a[4][4];  用指针数组表示数组a, 就是把a看成4个一维数组, 并说明一个有4个元素的指针数组pa,用于集中存放a的每一行元素的首地址,且使指针数组的每个元素pa[i]指向a的相应行。于是可以用指针数组名pa或指针数组元素pa[i]引用数组a的元素。  指针数组pa的说明和赋值如下:

int *pa[4], a[4][4];  pa[0]=&a[0][0]; 或pa[0]=a[0];  pa[1]=&a[1][0]; 或pa[1]=a[1];  pa[2]=&a[2][0]; 或pa[2]=a[2];  pa[3]=&a[3][0]; 或pa[3]=a[3];  *(*(pa+i)+0), *pa[i]或*(pa[i]+0)(i=0, 1, 2, 3)引用第i行第0列元素 a[i][0] ; *(*(pa+i)+1)或*(pa[i]+1)引用第i行第1列元素 a[i][1]; …。

用指针数组表示二维数组在效果上与数组的下标表示是相同的,只是表示形式不同。用指针数组表示时,需要额外增加用作指针的存贮开销;但用指针方式存取数组元素比用下标速度快,而且每个指针所指向的数组元素的个数可以不相同。例如,可用有5个元素的指针数组和5个不同长度的整型数组来描述下面的三角矩阵:

存贮三角矩阵的数组和每一行的指针可说明如下:  int a1[1], a2[2], a3[3], a4[4], a5[5], *pa[5];  下面的语句使pa的每个元素指向三角矩阵的每一行:  pa[1]=&a1[0];  pa[2]=&a2[0];  pa[3]=&a3[0];  pa[4]=&a4[0];  pa[5]=&a5[0];

8.4 指 针 与 函 数 8.4.1 指向函数的指针 C语言可以定义指向函数的指针,函数型指针的定义形式: 8.4 指 针 与 函 数 8.4.1 指向函数的指针 C语言可以定义指向函数的指针,函数型指针的定义形式: 类型标识符 (*指针名)(); 例如:  int (*fp)(); 说明: fp是指向int类型函数的指针。与指向数组的指针说明类似,说明符中用于改变运算顺序的()不能省。如果将(*fp)()写成* fp(), 则 fp成为返回值为指针类型的函数

例 8.16 指向函数的指针。  设一个函数operate,在调用它的时候,每次实现不同的功能。输入a和b两个数,第一次调用operate得到a和b中最大值,第二次得到最小值,第三次得到a与b之和。 main() {  int max(), min(), sum(), a, b; /* 必须进行函数声明, 否则无法调用 */ printf("Enter two number: ");  scanf("%d%d", &a, &b);  printf("max="); operate(a, b, max);  printf("min="); operate(a, b, min);  printf("sum="); operate(a, b, sum);

} max(int x, int y) {  if(x>y) return(x);  else return(y);  min(int x, int y) if(x<y) return(x);  sum(int x, int y) return(x+y);  operate(int x, int y, int (*fun)()) printf("%d\n", (*fun)(x, y));  }

程序运行情况:  Enter two number: 5 9 max=9 min=5 sum=14

8.4.2 返回指针的函数 C的函数可以返回除数组,共用体变量和函数以外的任何类型数据和指向任何类型的指针。 指针函数定义的一般形式:  类型标识符 *函数名(参数表){ } 其中“*函数名(参数表)”是指针函数定义符。 例如:  int *a(int x, int y){ }

例 8.17 指针函数 #include<string.h> #define STRLEN 81 例 8.17 指针函数 #include<string.h> #define STRLEN 81 #include <stdio.h> char *maxstr(char *str1, char *str2) {  if(strcmp(str1, str2)>=0) return(str1);  else return(str2);  } main() char string1[STRLEN], string2[STRLEN], *result;  printf("Input two strings: \n");  scanf("%s%s", string1, string2);  result=maxstr(string1, string2);  printf("The max string is: %s\n", result); 

程序运行情况:  Input two strings:  abcde abcee The max string is: abcee

8.5 复 杂 指 针 8.5.1 指向指针的指针 定义了指针pointer,它指向char型,用它可以存放字符型变量的地址,并且可以用它对所指向的变量进行间接访问。 进一步定义:  char **p-p;  从运算符*的结合性可以知道, 上述定义相当于:  char *(*p-p);

例 8.18 指向指针的指针。 main() {  int a, *pointer, **p-p;  a=20;  例 8.18 指向指针的指针。 main() {  int a, *pointer, **p-p;  a=20;  pointer=&a;  p-p=&pointer;  printf("%d, %u, %u\n" , a, pointer, p-p);  printf("%d, %u, %d\n", *pointer, *p-p, * *p-p);  }

运行结果:  20, 2000, 2050 20, 2000, 20 图 8.12 内存分配表

例 8.19 指向指针的指针。 main() {  static char *country[]={"CHINA", "ENGLAND", “ FRANCE", "GERMANY"};  char * *p;  int i;  for(i=0; i<4; i++) p=country+i;  printf("%s\n", *p);  } }

运行结果:  CHINA ENGLAND FRANCE GERMANY

8.5.2 命令行参数 例 8.20 echo程序。 #include<stdio.h> 8.5.2 命令行参数 例 8.20 echo程序。 #include<stdio.h> main(int argc, char *argv[]) {  int i;  for(i=1; i<argc; i++) printf("%s%s", argv[i], (i<argc-1)? " ": "\n");  printf("\n");  return 0;  }

程序运行的命令行情况:  echo hello world  运行结果:  hello world argv[0]为所调用程序的名字,所以argc至少为1。如果argc为1,则在程序名后面没有命令行参数。

例 8.21 命令行的三个参数,前两个为两个整数,第三个确定程序输出的为最大值还是最小值。 #include<stdio.h> #include<stdlib.h> #include<string.h> int max(int x, int y) {  return(x>y?x: y);  } int min(int x, int y) return(x>y?y: x);  }

main(int argc, char *argv[]) {  int a, b;  char *operate-flag;  if(argc<2) printf("usage: abc integer1 interger2 operate-flag\n");  exit(0);  } a=atoi(argv[1]);  b=atoi(argv[2]);  operate-flag=argv[3];  if(strcmp(operate-flag, "max")==0)

程序生成abc.exe后, 设命令行为 abc 20 30 max 输出为 The max of 20 and 30 is: 30 printf("The %s of%s and %s is: %d\n", argv[3], argv[1], argv[ 2], max(a, b));  else if(strcmp(operate-flag, "min")==0)  printf("The %s of %s and %s is: %d\n", argv[3], argv[1], argv [2], min(a, b));  else  printf("operate-flag should be max or min\n");  } 程序生成abc.exe后, 设命令行为 abc 20 30 max 输出为 The max of 20 and 30 is: 30

8.5.3 复杂指针的理解 注意:(1) 数组的元素不能为函数(可以为函数的指针)。 (2) 函数的返回值不能为数组或函数(可以为函数或数组的指针)。 *是指针类型的标志,[ ]是数组类型的标志,( )是函数类型的标志。( )和[ ]的优先级高于*,当[ ]、 *或( )和*同时出现时,先解释()和[]后解释*;()和[]属于同一优先级,二者同时出现时,按从左到右顺序解释; 整个说明符解释完之后,再加上类型标识符就是最终的解释。()也用于改变由优先级和结合性隐含的运算顺序,对嵌套的(),从内向外解释。

(1) char **pp;  pp: 指向字符指针的指针。  (2) int (*daytab)[13];  daytab: 指向由13个整型元素组成的数组的指针。  (3) int *daytab[13];  daytab: 由13个整型指针构成的指针数组。  (4) void *comp();  comp: 返回值为空类型指针的函数。  (5) void (*comp)();  comp: 指向无返回值函数的指针。

(6) int *p(char *a); p是一个函数, 它的形参是一字符型指针, 它的返回值是一整型指针。  (7) int (*p)(char*a); p是一个指针, 它指向一个函数, 函数有一字符指针作形参, 返回值为整型量。 (8) int p(char (*a) [ ]);  p是一个返回整型量的函数, 它有一个形参, 形参的类型是指向字符数组的指针。 (9) int *p(char *a[ ]);  p是一个函数, 返回一整型指针, 它的形参是一个字符指针数组。