
《第7章_指针-1(指针变量做参数、字符指针)》由会员分享,可在线阅读,更多相关《第7章_指针-1(指针变量做参数、字符指针)(32页珍藏版)》请在文档大全上搜索。
1、第第7 7章章 指针指针 指针是指针是C语言的一个重要概念,也是语言的一个重要概念,也是C语言的重语言的重要特色。要特色。 通过指针可以表示复杂的数据结构;实现动态分通过指针可以表示复杂的数据结构;实现动态分配内存和使用内存;方便处理字符串;有效地访问数配内存和使用内存;方便处理字符串;有效地访问数组;能带出函数的多个运算结果;能直接处理内存地组;能带出函数的多个运算结果;能直接处理内存地址等。址等。 掌握指针的应用,可使程序简洁、紧凑、高效!掌握指针的应用,可使程序简洁、紧凑、高效!不掌握指针就没掌握不掌握指针就没掌握C的精华!的精华!第第7章章 指针指针7.1 指针概述指针概述7.2 指针
2、和数组间的关系指针和数组间的关系7.3 指针数组指针数组7.4 带参数的带参数的main()函数函数7.5 动态数组的实现动态数组的实现 7.1 指针(指针(Pointer)概述)概述一、问题的提出一、问题的提出 -为什么需要使用指针?为什么需要使用指针?void Swap(int x,int y) int temp; temp = x; x = y; y = temp;#includevoid Swap(int x,int y);int main(void) int a, b; a = 15; b = 8; Swap(a, b); printf( a=%d,b=%d ,a,b); retur
3、n 0;该程序能实现两数该程序能实现两数的交换吗?的交换吗?二、地址和指针的概念二、地址和指针的概念(一)(一) 内存单元的地址内存单元的地址 和其中的内容和其中的内容 内存单元的地址内存单元的地址 计算机的内部存储器是由若干计算机的内部存储器是由若干个单元组成的,每一个单元中可存个单元组成的,每一个单元中可存放一个字节的信息。为了能区分不放一个字节的信息。为了能区分不同的单元,对这些单元分别编号,同的单元,对这些单元分别编号,此编号即为内存单元的地址。此编号即为内存单元的地址。 FAC0 FAC1 FAC2内部存储器内部存储器 FAC4 FAC3 FAC0 FAC1 FAC5内部存储器内部存
4、储器 FAC2 FAC4 FAC6 FAC7 FAC8 FAC9 FACF FACA FACB FACC FACD FACE FAC3FAC02. 指针及指针变量指针及指针变量 指针指针(也叫变量的指针也叫变量的指针): 在在C中,将地址形象化地称为指针。一个变量的中,将地址形象化地称为指针。一个变量的地址称为该变量的指针。地址称为该变量的指针。 指针变量:指针变量: 在在C中,有一种特殊的变量,它是专门用来存放中,有一种特殊的变量,它是专门用来存放另一个变量地址的变量,我们称它为指针变量。另一个变量地址的变量,我们称它为指针变量。 指向(也叫指针所指变量):指向(也叫指针所指变量): 通过指
5、针变量中的指针(地址)值所能找到的变通过指针变量中的指针(地址)值所能找到的变量单元,称之为:地址量单元,称之为:地址“指向指向”变量单元(变量单元(也叫指也叫指针所指变量针所指变量)。)。int a = 10, *p;p = &a;三、如何定义指针变量?三、如何定义指针变量? 定义指针变量的一般形式定义指针变量的一般形式 类型标识符类型标识符 *指针变量名指针变量名注意注意: (1)类型标识符用来说明指针变量能制向的变类型标识符用来说明指针变量能制向的变 量类型,也叫量类型,也叫指针的基类型;指针的基类型; (2)“*”表示声明指针变量;指针变量名由用户指定。表示声明指针变量;指针变
6、量名由用户指定。 (3)指针变量是要分配存储空间的,大小为指针变量是要分配存储空间的,大小为4字节,必须注意字节,必须注意的是其中只能存放地址值,而不能存储一般的数据。的是其中只能存放地址值,而不能存储一般的数据。例如:例如:int *pointer_1, *pointer_2; (可以存放整型变量的地址可以存放整型变量的地址) float *pointer_3; (可以存放实型变量的地址可以存放实型变量的地址) char *pointer_4; (可以存放字符型变量的地址可以存放字符型变量的地址)int i,*p;p=&i;int *p;float *q;p=q;int i;floa
7、t *p;p=&i;int a=5,*p;p=a;指针变量只指针变量只存放地址存放地址!一个指针变量不能一个指针变量不能指向与其类型不同指向与其类型不同的变量的变量!我是正确的,我是正确的,你猜对了吗?你猜对了吗?应在类型相应在类型相同的指针变同的指针变量之间赋值量之间赋值 2. &与与*操作符操作符例例 1: 通过指针变量访问整型变量通过指针变量访问整型变量 (在调试状态下查看各变量的值在调试状态下查看各变量的值)#include int main(void )int a = 100, b = 10;int *p1, *p2;p1 = &a;p2 = &b;p
8、rintf(“%d,%dn”, a , b);printf(“%d, %dn”, *p1, *p2);printf(“%p,%pn”, &a , &b);printf(“%x, %xn”, p1, p2);printf(“%p,%pn”, &p1 , &p2);return 0;四、四、 指针的运算指针的运算(一)关系运算(一)关系运算指向同一种数据类型的两个指针变量才能进行关系运指向同一种数据类型的两个指针变量才能进行关系运算算值为值为1(真)或(真)或0(假)(假)p q p q p = q注意:是判断地址的大小,而绝对不是数据值的大小。注意:是判断地址的大
9、小,而绝对不是数据值的大小。不能与非指针类型变量进行比较,但可与不能与非指针类型变量进行比较,但可与NULL(为指为指针常量,即空(针常量,即空(0)值)值)进行等或不等的关系运算进行等或不等的关系运算判断判断p是否为空指针是否为空指针P = NULLp != NULL(二)赋值运算(二)赋值运算1.指针变量的赋值指针变量的赋值赋地址赋地址 指针变量在使用前一定要赋值;为指针变指针变量在使用前一定要赋值;为指针变量赋的值必须是一个地址。量赋的值必须是一个地址。int main(void) int *p; scanf(%d, p); int main(void) int a,*p = &
10、a; scanf(%d, p); 错!但TC下不报错VC下报错例如:理解如下指针变量的赋值结果:例如:理解如下指针变量的赋值结果:int main(void) int a = 10, b = 20, *p, *q; p = &a; /*使指针变量使指针变量p指向变量指向变量a */ q = &b; /*使指针变量使指针变量q指向变量指向变量b */ p = q; /*使使p指针变量获得指针变量指针变量获得指针变量q中的地址中的地址*/ /* 或者或者 q = p; */ printf(“a= %d b=%dn”, a, b); printf(“a= %d b=%dn”, *p,
11、 *q); return 0; *指针变量名指针变量名 = 例如:例如: int main(void) int a , b, *p, *q; p = &a; /*使指针变量使指针变量p指向变量指向变量a */ q = &b; /*使指针变量使指针变量q指向变量指向变量b */ *p = 10; /* 给给p指针所指变量指针所指变量a赋值为赋值为10 */ *q = *p + 20; /* 给给q指针所指变量指针所指变量b赋值为赋值为30 */ printf(“a=%d b=%dn” , a , b); return 0;五、指针变量作为函数参数五、指针变量作为函数参数 函数的参
12、数不仅可以是整型、实型、字符型等数函数的参数不仅可以是整型、实型、字符型等数据,还可以是指针类型。它的作用是将一个变量的地据,还可以是指针类型。它的作用是将一个变量的地址传到另一个函数中址传到另一个函数中_单向传址。单向传址。1 1、函数的声明形式:、函数的声明形式: 函数结果类型名函数结果类型名 函数名(函数名(类型名类型名 * *指针变量指针变量) ; 注意:函数的形参为指针类型,它用来接受函数调用注意:函数的形参为指针类型,它用来接受函数调用时对应实参的地址。时对应实参的地址。2 2、函数的调用形式:、函数的调用形式: 函数名(函数名(指针变量名指针变量名 | &| &变
13、量名变量名 )注意:实参数必须是变量的地址值或指针变量。注意:实参数必须是变量的地址值或指针变量。例如:指针作函数参数的简单形式例如:指针作函数参数的简单形式#include void f(double *p);int main(void) double x1; f(&x1); /*调用函数时实参为变量地址调用函数时实参为变量地址*/ void f(double *p) /*函数的形式参数为指针变量函数的形式参数为指针变量*/ 变量void Swap(int *x,int *y) int temp; temp = *x; *x = *y; *y = temp;int main(void
14、) int a, b; a = 15; b = 8; Swap( &a, &b ); printf( a=%d,b=%d ,a,b); return 0;void Swap(int x,int y) int temp; temp = x; x = y; y = temp;int main(void) int a, b; a = 15; b = 8; Swap(a, b); printf( a=%d,b=%d ,a,b); return 0;程序程序 1程序程序 2 例例1:编写函数实现两数的互换:编写函数实现两数的互换主调函数主调函数被调被调函数函数实实 参参形形 参参结果有何
15、不同?结果有何不同?主调函数主调函数被调函数被调函数15ab实实 参参形形 参参8程序程序 1xytemp主调函数主调函数被调函数被调函数&a实实 参参形形 参参&b程序程序 2xytempab815例例2 2:利用指针变量将函数的多个运算结果带:利用指针变量将函数的多个运算结果带出函数出函数_这是指针最重要的这是指针最重要的应用之一!应用之一!如定义一个根据圆的半径,计算该圆的直径、周如定义一个根据圆的半径,计算该圆的直径、周长和面积的函数,然后调用该函数。长和面积的函数,然后调用该函数。#include #define PI 3.1415926double Circle(d
16、ouble r, double *c1, double *s1);int main(void)double r, ll, cc, ss;printf(Please input r data:);scanf(%lf, &r);ll = Circle(r, &cc, &ss);printf(l=%.2f c=%.2f s=%.2fn, ll, cc, ss);return 0;Double Circle(double r, double *c1, double *s1)double l1;l1 = 2 * r;*c1 = 2 * PI * r;*s1 = PI * r *
17、r;return l1;注意:该函数计算的圆直径值是用注意:该函数计算的圆直径值是用return字句带出字句带出函数的,而圆的周长和面积值是通过指针带出函数函数的,而圆的周长和面积值是通过指针带出函数的!的!swap函数的几种错误形式(函数的几种错误形式(1/21/2)swap函数的几种错误形式(函数的几种错误形式(2/22/2)void sub1(char a, char b) char c; c=a; a=b; b=c;void sub2(char *a, char b) char c; c=*a; *a=b; b=c;void sub3(char *a, char *b) char c;
18、 c=*a; *a=*b; *b=c;以下程序的输出结果是(以下程序的输出结果是( )。)。#include void sub1(char a, char b);void sub2(char *a, char b);void sub3(char *a, char *b); int main(void)char a, b; a=A; b=B; sub3 (&a, &b); putchar(a); putchar(b); a=A; b=B; sub2 (&a, b); putchar(a); putchar(b); a=A; b=B; sub1 (a, b); putcha
19、r(a); putchar(b);return 0;六、字符指针作为函数参数六、字符指针作为函数参数(一)串的表示:字符数组或字符指针(一)串的表示:字符数组或字符指针 C语言并没有为字符串提供任何专门的表示法,语言并没有为字符串提供任何专门的表示法,完全是使用字符数组和字符指针来处理字符串。完全是使用字符数组和字符指针来处理字符串。字符串字符串一串以一串以0结尾的字符结尾的字符字符数组字符数组每个元素都是字符类型的数组每个元素都是字符类型的数组char string100;字符指针字符指针指向字符类型的指针指向字符类型的指针char *p;(二)字符指针变量与字符数组的区别(二)字符指针变量
20、与字符数组的区别1、定义方法不同、定义方法不同 数组数组 char str10; 指针指针 char *ptr; 2、赋值方法不同、赋值方法不同 数组数组 char str10; str = ”china”; /*错误错误*/ strcpy(str,”china”); /*正确正确*/ 指针指针 char *ptr; ptr = ”china”;(三)使用字符指针的注意事项(三)使用字符指针的注意事项字符指针变量必须有明确的指向,否则字符指针变量必须有明确的指向,否则使用是危险的。使用是危险的。( (思考:为什么呢?思考:为什么呢?) ) 例如,输入字符串时例如,输入字符串时 char *a;
21、 scanf(%s, a); /*错误错误*/ 应为:应为: char *a; char str10; a = str; scanf(%s, a); /*正确正确*/#include void MyStrcpy(char *p2, const char *p1)while (*p1 != 0) *p2 = *p1; p1+; p2+; *p2 = 0; 例例1:字符串拷贝:字符串拷贝用字符指针编程用字符指针编程int main(void)char a80, b80;printf(“Please enter a string:”);gets(a);MyStrcpy(b,a);printf(“Th
22、e copy is:”); puts(b); return 0; c a t 0 a a6 a5 a4 a3 a2 a1 a0p1 b b11 b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0p2当只允许函数访问地址内容,不允许修改当只允许函数访问地址内容,不允许修改时,可以把函数的指针参数定义为时,可以把函数的指针参数定义为const例例2:P808 .c 两个字符串的交错插入连接两个字符串的交错插入连接-用字符指针编程实现。用字符指针编程实现。#include #define N 128void conj(char *string1, char *string2) ;in
23、t main(void)char str1N * 2, str2N;printf(Please input string1:);gets(str1);printf(Please input string2:);gets(str2);void conj(char *string1, char *string2)char bakN * 2, *p1, *q1;int i;i = 0;p1 = string1;q1 = string2;for ( ; *p1 != 0 & *q1 != 0; i = i + 2, p1+, q1+)baki = *p1;baki + 1 = *q1;whil
24、e (*p1 != 0)baki = *p1;i+;p1+;while (*q1 != 0)baki = *q1;i+;q1+; baki = 0;strcpy(string1, bak);以下程序的输出结果是(以下程序的输出结果是( )。)。#include#include#include#includevoid fun(char void fun(char * *s);s);int main(void)int main(void) char char * *a=abcd;a=abcd; int k; int k; fun(a); fun(a); puts(a); puts(a); return 0; return 0; void fun(char void fun(char * *s)s)int x, y;int x, y; char c; char c; for(x=0, y=strlen(s)-1; xy; x+, y-) for(x=0, y=strlen(s)-1; xy; x+, y-) c=sy; sy=sx; sx=c; c=sy; sy=sx; sx=c; A) dcbaA) dcbaB) abcdB) abcdC) abcddebaC) abcddebaD) aabbD) aabb课课堂堂习习题题: