- 指针
- 直接访问与间接访问
- 指针变量
- 定义指针变量
- 引用指针变量
- 指针变量作为函数参数
- 通过指针引用数组
- 通过指针引用数组元素
- 通过指针引用多维数组
- 字符指针变量和字符数组的比较
- 指向函数的指针
- 指向函数的指针的优势
- 返回指针值的函数
- 指针数组
- 例题汇总
- 例8.1初识指针
- 例8.2引用指针变量(排序)
- 例8.3指针变量函数
- 例8.4指针变量函数的错误示范
- 例8.5
- 例8.6通过指针引用数组元素(输出数组元素)
- 例8.7通过指针输出数组元素(最快读取)
- 例8.8通过指针引用数组(反顺序)
- 例8.9用指针变量作参数
- 例8.10形参采用指针变量(便于理解,推荐使用)
- 例8.16输出字符串
- 例8.17采用指针实现字符串输出
- 例8.18复制字符串
- 例8.19复制字符串(使用指针变量)
- 例8.20字符指针作函数参数(复制字符串)
- 例8.21改变指针变量的值
- 例8.22通过指针调用函数
- 例8.23通过指针调用函数
- 例8.24指向函数的指针
- 例8.25返回指针的函数
- 例8.26
- 例8.27指针数组
- 例8.28指向指针的指针变量
- 例8.29
在程序中定义一个变量时,系统会为该变量创建一个存储单元。存储单元的编号被称为地址。程序可以通过地址找到变量,即地址指向变量,因此C语言中将地址形象的称为“指针”。
指针说明了变量的位置信息,但无法确定该变量占用了多少个存储单元。因此若是要有效地存取一个数据,除了需要指针(即位置信息)外,还需要该数据的类型信息,即数据类型。综上所述,C语言中的地址包括位置信息和类型信息两部分,可以称其为“带类型的地址”。
如:a为整型变量,&a一般称它为“变量a的地址”,确切的说,它是“整型变量a的地址”,一般简称“地址”。
- 直接访问
通过变量名进行的访问,称为“直接访问”
如:
int a = 3;
- 间接访问
将变量i的地址存放在另一变量中,然后通过该变量来找到变量i的地址,从而访问变量i。这类专门存放另一个变量的地址的变量,称为“指针变量”。指针变量的值是地址。
指针变量是专门用来存放变量的地址(即指针)的变量。指针变量的值是地址。
定义指针变量定义指针变量的一般形式为:
类型名 * 指针变量名;
一个变量的指针的含义包含两个方面:一是以存储单元编号表示的纯地址;二是它指向的存储单元的数据类型;指向整型数据的指针类型表示为“int *”,读作“指向int的指针”或简称“int 指针”。
例如:
int * pointer_1, * pointer_2;引用指针变量
- 给指针变量赋值:
p = &a; //把a的地址赋给指针变量p
- 引用指针变量指向的变量
* p = 1; //将整数1赋给p当前所指向的变量
printf("%d", * p); //输出指针变量p所指向的变量的值
| 运算符 | 说明 |
|---|---|
| & | 取地址符,&a是变量a的地址 |
| * | 指针运算符,* p代表指针变量p指向的对象 |
指针变量作为函数参数,它的作用是将一个变量的地址传送给另一个函数中。可实现,通过调用函数使变量的值发生变化。
见例8.3
为了使函数中改变了的变量值能被主函数所用,应该用指针变量作为函数参数,在函数的执行过程中使指针变量所指向的变量值发生变化,函数调用结束后,这些变量值的变化依然保留了下来,这样就实现了“通过调用函数使变量的值发生变化”
数组元素的指针就是数组元素的地址,通常数组元素的引用采用下标法(即a[i]),也可以是用指针法,即通过指向数组元素的指针找到所需的元素。
p = &a[0]; //p的值是a[0]的地址 p = a; //与上一句等价,p的值是数组a首元素的地址
数组名其实就是一种指针变量,使用数组名作参数,其实就是传递数组首元素的地址,所以形参其实就是指针变量
如
void fun(int arr[], int n) //arr按指针变量处理,等价于void fun(int * arr, int n){}
{
..........
}
通过指针引用数组元素
-
引用数组元素时指针的运算
当指针指向数组元素时,才会涉及到指针的运算。
若指针已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素。 -
引用数组元素
- 下标法,如a[i]形式;
- 指针法,如*(a+i)或 *(p+i)。a是数组名,p是指向数组元素的指针变量
使用指针变量直接指向元素,读取速度更快。不必每次都重新计算地址。
通过指针引用多维数组多维数组
int a[3][4] = {{1,3,5,7},{9,11,13,15},{17,19,21,23}};
已知a[0]和*(a+0)等价,a[1]和 (a+1)等价,因此a[0]+1与(a+0)+1都是&a[0][1]
字符指针变量和字符数组的比较- 值不同:字符数组由若干各元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址。
- 赋值方式不同:可以对字符指针变量赋值,但不能对数组名赋值。
- 初始化的含义不同:数组可以在定义时对各元素赋初值,但不能用赋值语句对字符数组中全部元素整体赋值。
如:
char *a; a = "I love China.";
是合规的
```c char a[]; a[] = "I love China."
是不合规的
4. 存储单位的内容不同:编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元。
5. 值的改变:指针变量的值时可以改变的,而字符数组名代表一个固定的值,不能改变。
6. 字符数组中各元素的值时可以改变的,但字符指针变量指向的字符串常量中的内容是不可以被取代的。
7. 引用数组元素。数组更方便
8. 用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串。
char *format; format = "a=%d,b=%fn"; printf(format, a, b);
等价于
printf("a=%d,b=%dn", a, b);
指向函数的指针
定义指向函数的指针的一般形式为:
*类型名 (指针变量名)(函数参数表列)
每次调用函数时给出不同的函数名最为实参即可,调用函数不必作任何修改。这种方法是符合结构化设计方法原则的。
见例8.24
定义返回指针值的函数的原型为
*类型名 函数名(参数列表)
如:
int *a(int x, int y)
{
……
}
*的运算级别较低,a(int x, int y)是一个函数。前面的 int *,说明这是一个指数类型的函数
指针数组指针数组的每一个元素都是指针,即指针数组的每一个元素都存放了一个地址。
指针数组的定义形式为:
*类型名 数组名[数组长度]
通过指针变量访问整型变量
#include例8.2引用指针变量(排序)int main() { int a = 100, b = 10; //整型变量a,b int * pointer_1, * pointer_2; //指针型变量pointer_1,pointer_2 pointer_1 = &a; //将整型变量a的地址,存入指针变量pointer_1中 pointer_2 = &b; //将整型变量b的指针,存入指针变量pointer_2中 printf("a=%d,b=%dn", a, b); //输出整型变量的值 printf("pointer_1=%d,pointer_2=%d", * pointer_1, * pointer_2); //输出指针变量的值,*为取值符号,* pointer_1的意思为地址为pointer_1的整型存储单元中的存储的值 return 0; }
输入a和b两个整数,按先大后小的顺序输出a和b
#includeint main() { int * p1, * p2, * p, a, b; printf("请输入两个整数:"); scanf("%d%d", &a, &b); p1 = &a; //将变量a的地址存入指针变量p1中 p2 = &b; //将变量b的地址存入指针变量p2中 if(a < b) //如果a 例8.3指针变量函数 同例8.2
#include例8.4指针变量函数的错误示范int main() { void swap(int *p1, int *p2); int a, b; int *pointer_1, *pointer_2; printf("请输入两个整数:"); scanf("%d%d", &a, &b); pointer_1 = &a; pointer_2 = &b; if(a < b) swap(pointer_1, pointer_2); printf("最大值为:%dn最小值为:%d", a, b); } void swap(int *p1, int *p2) { int temp; temp = *p1; *p1 = *p2; *p2 = temp; } 同例8.2
#includeint main() { void swap(int *p1, int *p2); int a, b; int *pointer_1, *pointer_2; printf("请输入两个整数:"); scanf("%d%d", &a, &b); pointer_1 = &a; pointer_2 = &b; if(a < b) swap(pointer_1, pointer_2); printf("最大值为:%dn最小值为:%d", *pointer_1, *pointer_2); return 0; } void swap(int *p1, int *p2) //swap函数,交换p1与p2的指向 { int *p; p = p1; p1 = p2; p2 = p; } 例8.5
C语言中实参变量和形参变量之间的数据传递是单向的值传递方式,用指针变量作函数参数时同样要遵循这一规则。不可能通过执行调用函数来改变实参指针变量的值,但是可以改变实参指针变量所指变量的值。输入3个整数a,b,c要求按由大到小的顺序将它们输出。
#include例8.6通过指针引用数组元素(输出数组元素)int main() { void exchange(int *q1, int *q2, int *q3); //函数声明,由大到小排列 int a, b, c, *p1, *p2, *p3; printf("请输入3个整数:n"); scanf("%d%d%d", &a, &b, &c); p1 = &a; p2 = &b; p3 = &c; exchange(p1, p2, p3); printf("由大到小的顺序为:%d,%d,%d", a, b, c); return 0; } void exchange(int *q1, int *q2, int *q3) { void swap(int *pt1, int *pt2); //函数声明,交换两个数 if(*q1 < *q2) swap(q1,q2); if(*q1 < *q3) swap(q1,q3); if(*q2 < *q3) swap(q2,q3); } void swap(int *pt1, int *pt2) { int temp; temp = *pt1; *pt1 = *pt2; *pt2 = temp; } 有一个整型数组a,有10个元素,输出数组中的全部元素。
#include例8.7通过指针输出数组元素(最快读取)int main() { int a[10]; int *p; //int i; printf("请输入10个整数:n"); for(p=a; p<(a+10); p++) //直接将输入的数值存入指定的存储单独 scanf("%d", p); printf("输入的数组元素为;n"); for(p=a; p<(a+10); p++) printf("%3d", *p); return 0; } 同上
#include例8.8通过指针引用数组(反顺序)int main() { int *p, i, a[10]; p = a; //将数组元素a[0]的地址赋值到p中 printf("请输入10个整数:n"); for(i=0; i<10; i++) scanf("%d", p++); //循环结束后,p的值为(a+10)的地址 p = a; //若要正确的输出数组a的元素,需将p指向的地址复原到a[0]上 for(i=0; i<10; i++) printf("%3d", *p++); printf("n"); return 0; } 将数组a中n个整数按相反顺序存放
#include例8.9用指针变量作参数int main() { void inv(int x[], int n); //函数声明,交换数组顺序 int i, a[10] = {3,7,9,11,0,6,7,5,4,2}; printf("原数组内容为:n"); for(i=0; i<10; i++) printf("%3d", a[i]); printf("n"); inv(a, 10); //运行inv函数 printf("交换后的数组内容为:n"); for(i=0; i<10; i++) printf("%3d", a[i]); printf("n"); return 0; } void inv(int x[], int n) //x为数组名 { int temp, i, j, m; m = (n-1)/2; for(i=0; i<=m; i++) { j = n-1-i; temp = x[i]; x[i] = x[j]; x[j] = temp; } } 同例8.8
#include例8.10形参采用指针变量(便于理解,推荐使用)int main() { void inv(int *x, int n); //函数声明,输入数组名和数组元素个数,交换数组元素 int i, arr[10], *p=arr; //若采用指针变量作实参,必须先使指针变量又确定值,指向一个已定义的对象 printf("请输入十个整数:n"); for(i=0; i<10; i++) scanf("%d", p++); printf("n"); p = arr; //将指针p定位到数组元素a[0]上 inv(p, 10); //交换拥有10个元素的数组a //若采用指针变量作实参,必须先使指针变量又确定值,指向一个已定义的对象 printf("交换顺序后的数组为:n"); for(i=0; i<10; i++) printf("%3d", *p++); printf("n"); return 0; } void inv(int *x, int n) //inv函数,输出数组名和数组元素的个数,交换数元素顺序 { int *p, m, temp, *i, *j; m = (n-1)/2; i = x; j = x+n-1; p = x+m; for(; i<=p; i++,j--) { temp = *i; *i = *j; *j = temp; } } 对10个整数按由大到小的顺序排序
#include例8.16输出字符串int main() { void sort(int x[], int n); //函数声明,输入数组名和数组元素个数, 采用选择法排序 int i, *p, a[10]; p = a; printf("请输入十个整数:n"); for(i=0; i<10; i++) scanf("%d", p++); p = a; sort(p, 10); //输入数组名和数组元素个数,采用选择法排序 for(i=0; i<10; i++) printf("%3d", *p++); return 0; } void sort(int x[], int n) //选择法,由大到小排序 { int i, j, k, t; for(i=0; i x[k]) k = j; if(k!=i) { t = x[i]; x[i] = x[k]; x[k] = t; } } } 定义一个字符数组,在其中存放字符串“I love China”,输出字符串和第8个字符
#include例8.17采用指针实现字符串输出int main() { char string[] = "I love China!"; //输入字符串 printf("%sn", string); //输出字符串 printf("%cn", string[7]); //输出字符串第8个元素 return 0; } 同例8.16
#include例8.18复制字符串int main() { char *string = "I love China!"; //将“” printf("%sn", string); printf("%cn", *(string+7)); return 0; } 将字符串a复制为字符串b,然后输出字符串b
#include例8.19复制字符串(使用指针变量)int main() { char a[] = "I am a student."; char b[20]; int i; for(i=0; *(a+i)!=' '; i++) //采用类指针的方式复制字符串 *(b+i) = *(a+i); *(b+i) = ' '; printf("字符串a为:%sn", a); printf("字符串b为:%sn", b); return 0; } 同例8.18
#include例8.20字符指针作函数参数(复制字符串)int main() { char a[] = "I am boy.", b[20], *p1, *p2; p1 = a; p2 = b; for(; *p1 !=' '; p1++, p2++) *p2 = *p1; *p2 = ' '; printf("字符串a为:%sn", a); printf("字符串b为:%sn", b); return 0; } 用函数调用实现字符串复制
#includeint main() { void copy_string(char from[], char to[]); char a[] = "I am a teacher."; char b[] = "You are a sutdent."; printf("字符串a的内容为:%sn字符串b的内容为:%sn", a, b); copy_string(a, b); printf("n字符串a的内容为:%sn字符串b的内容为:%sn", a, b); return 0; } void copy_string(char from[], char to[]) { int i; while(from[i] != ' ') { to[i] = from[i]; i++; } to[i] = ' '; } #include例8.21改变指针变量的值int main() { void copy_string(char from[], char to[]); //函数声明, char a[] = "I am a teacher."; char b[] = "You are a student."; char *from = a, *to = b; printf("字符串a的内容为:%sn字符串b的内容为:%sn", a, b); copy_string(from, to); //将字符串from的内容复制到字符串to中 printf("n字符串a的内容为:%sn字符串b的内容为:%sn", a, b); return 0; } void copy_string(char from[], char to[]) //输出两个字符串,将字符串from内容复制到字符串to中 { int i = 0; while(from[i] != ' ') { to[i] = from[i]; i++; } to[i] = ' '; } #include例8.22通过指针调用函数int main() { char *a = "I love China.n"; a = a+7; printf("%sn", a); return 0; } 求整数a和b中的最大值
#include例8.23通过指针调用函数int main() { int max(int x, int y); int (*p)(int, int); int a, b, c; p = max; printf("请输入两个整数:n"); scanf("%d%d", &a, &b); c = (*p)(a, b); printf("%d和%d中的较大值为:%dn", a, b, c); return 0; } int max(int x, int y) { int z; z = x>y ? x : y; return z; } 输入两个整数,然后让用户选择1或2,选1时调用max函数,输出二者中的最大值。选2时调用min函数,输出二者中的最小值。
#include例8.24指向函数的指针int main() { int max(int, int); //函数声明,输入两个整数求最大值 int min(int, int); //函数声明,输入两个整数求最小值 int (*p)(int, int); //指向函数的指针 int a, b, c, n; printf("请输入两个整数:n"); scanf("%d%d", &a, &b); printf("n请选择要进行的操作:n"); printf("t1.求最大值。nt2.求最小值。n"); scanf("%d", &n); if(n==1) p = max; else if(n==2) p = min; //若n为1,将max函数的地址存入p中 else printf("请输入数字1或2。"); //若n为2,将min函数的地址存入p中 c = (*p)(a,b); //运行地址为p的函数 if(n==1) printf("n最大值为:%d", c); else if(n==2) printf("n最小值为:%d", c); return 0; } int max(int x, int y) //max函数,求输入两个数的最大值 { int z; if(x>y) z = x; else z = y; return z; } int min(int x, int y) //min函数,求输入两个数的最小值 { int z; if(x>y) z = y; else z = x; return z; } 有两个整数a和b,由用户输入1,2或3.若输入1,程序就给出a和b中的最大值,输入2,程序就给出a和b中的最小值,输出3则求a与b的和。
#include例8.25返回指针的函数int main() { void fun(int x, int y, int (*p)(int, int)); //fun函数声明 int max(int, int); //max函数声明 int min(int, int); //min函数声明 int add(int, int); //add函数声明 int a, b, n; printf("请输入两个整数:"); scanf("%d%d", &a, &b); printf("n请选择:n"); printf("1.求最大值n2.求最小值n3.求和nn"); scanf("%d", &n); if(n==1) fun(a, b, max); else if(n==2) fun(a, b, min); else if(n==3) fun(a, b, add); return 0; } void fun(int x, int y, int (*p)(int ,int)) //fun函数,输入两个整数和所需的函数,输出函数运行结果 { int result; result = (*p)(x, y); printf("%dn", result); } int max(int x, int y)//max函数,输入两个整数,求最大值 { int z; if(x>y) z = x; else z = y; printf("最大值为:"); return z; } int min(int x, int y) //min函数,输入两个整数,求最小值 { int z; if(x>y) z = y; else z = x; printf("最小值为:"); return z; } int add(int x, int y)//add函数,输入两个整数,求和 { int z; z = x+y; printf("两数的和为:"); return z; } 有a个学生,每个学生有b门课程的成绩。要求在用户输入学生序号以后,能输出该学生的全部成绩。
#include例8.26int main() { float *search(float (*pointer)[4], int n); //函数声明 float score[][4] = {{60,70,80,90},{56,89,67,88},{34,78,90,66}}; float *p; int i, k; printf("请输入学生编号:"); scanf("%d", &k); printf("n学生编号为%d的学生成绩为:n", k); p = search(score, k); for(i=0; i<4; i++) printf("%5.2ft", *(p+i)); printf("n"); return 0; } float *search(float (*pointer)[4], int n) //float函数,输入一个数组和一个整数 { //输出二维数组的列的第一个元素的地址 float *pt; pt = *(pointer+n); return pt; } 对例8.25中的学生,找出其中有不及格的课程的学生及其学生号。
#include例8.27指针数组int main() { float score[][4] = {{60,70,80,90},{56,89,67,88},{34,78,90,66}}; float *search(float (*pointer)[4]); //函数声明 float *p; int i, j; for(i=0; i<3; i++) { p = search(score+i); if(p==*(score+i)) { printf("学生%d:", i); for(j=0; j<4; j++) printf("%5.2f ", *(p+j)); printf("n"); } } return 0; } float *search(float (*pointer)[4]) //search函数,输入一维数组,返回指针 { int i = 0; float *pt; pt = NULL; for(; i<4; i++) if(*(*pointer+i)<60) pt = *pointer; return pt; } 将若干字符串按字母顺序输出
#include#include int main() { void sort(char *name[], int n); //函数声明 void print(char *name[], int n); //函数声明 char *name[] = {"Follow me","BASIC","Great Wall","FORTRAN","Computer design"}; int n = 5; sort(name, n); //调用sort函数,对字符串排序 print(name, n); //调用print函数,输出字符串 return 0; } void sort(char *name[], int n) //sort函数,对字符串排序 { char *temp; int i, j, k; for(i=0; i 0) //strcmp函数,是系统提供的字符串比较 k = j; if(k!=i) { temp = name[i]; name[i] = name[k]; name[k] = temp; } } } void print(char *name[], int n) //prnt函数,对输出字符串 { int i; for(i=0; i 例8.28指向指针的指针变量 #include例8.29int main() { char *name[] = {"Follow me","BASIC","Great Wall","FORTRAN","Computer design"}; char **p; int i; for(i=0; i<5; i++) { p = name+i; printf("%sn", *p); } return 0; } #includeint main() { int a[5] = {1,3,5,7,9}; int *num[5] = {&a[0],&a[1],&a[2],&a[3],&a[4]}; int **p, i; p = num; for(i=0; i<5; i++) { printf("%d ", **p++); } printf("n"); return 0; }



