第8章_指针
《C语言程序设计》第8章指针
10.3.3 指针变量和数组作函数参数 数组名作形参时,接收实参数组的起始地址;
作实参时,将数组的起始地址传递给形参数组。
引入指向数组的指针变量后,数组及指向数 组的指针变量作函数参数时,可有4种等价形式 (本质上是一种,即指针数据作函数参数):
(1)形参、实参都用数组名 (2)形参、实参都用指针变量 (3)形参用指针变量、实参用数组名 (4)形参用数组名、实参用指针变量
(4)指针变量的++、--与&、*的结合
对于指针变量的++、--与&、*的结合 使用,关键要注意按照运算符的优先级和 结合性进行。
例如: int a=2, *p; p=&a;
•表达式:(*p)++,按运算符的优先级,等价于 a++。其含义为:取出指针变量p所指向的内存单 元的值(即a的值),a的值加1,送回a的内存单 元,a的值变为3,p的值未发生变化,仍然指向 变量a。
程序说明:printf("%s\n",s);语句 通过指向字符串的指针变量s,整体引
用它所指向的字符串的原理:系统首先输出s 指向的第一个字符,然后使s自动加1,使 之指向下一个字符;重复上述过程,直至遇到 字符串结束标志。
main() { char string[ ]=”I love Beijing.”; printf(“%s\n”,string); }
3.数组元素的引用 数组元素的引用,既可用下标法,也可用
指针法。
10.3.2 通过指针引用数组元素 如果有“int a [10],*p=a;” ,则: (1)p+i和a+i都是数组元素a [i]的地址。
(2)*(p+i)和*(a+i)就是数组元素a [i]。 int a [3]; a [0]——*a a [1]——*(a +1) a [2]——*(a +2)
精品课件-C程序设计(第三版)(荣政)-第8章
第八章 指针
指针类型是对所有类型的指针的总称,指针的类型是指 针所指对象的数据类型。例如,pc是指向字符变量的指针, 简称字符指针。字符指针是基本类型的指针之一,除各种基 本类型之外,允许说明指向数组的指针、指向函数的指针、 指向结构体和共用体的指针以及指向各类指针的指针。在C 语言中只有指针被允许用来存放地址的值,其它类型的变量 只能存放该类型的数据。(很多书中用指针一词来指地址值, 或用指针变量来代表指针,阅读中应注意其具体含义。)
例8.2中指向整型的指针point在定义之后直接使用了,这 两条语句在编译时不会出现语法错误,但在使用时却几乎肯定 会出问题。表面上看,scanf()函数的参数要求给出的是地址, 而point的值就代表的是地址,但是point的值究竟是多少,也 就是说point究竟指向哪里,我们无法得知,在这种情况下就 对point指向的单元进行输入操作,将冲掉point指向的单元的 原有内容,假如这个单元是操作系统的所在处,就破坏了操作 系统,显然是一件危险的事。
为了理解指针的概念,程序员要有关于计算机如何在存储 器中存储信息的基本知识。以下简单地介绍个人计算机中存储 器存储的情况。
第八章 指针
个人计算机中CPU可以直接访问的,用来存储程序和数据 的记忆部件称为内存储器,内存储器由成千上万个顺序存储单 元组成,每个单元由一个惟一的地址标识。给定计算机的存储 器地址范围为从0到所安装的存储器数量的最大值。在计算机 上运行的每一个程序都要使用存储器。例如,操作系统要占用 一些计算机存储空间,每个应用程序也要占用计算机存储空间。 按照面向过程的结构化程序设计方法,程序代码和程序要处理 的数据是分开存储的,所以,一个程序在内存中要占两部分空 间:数据部分和指令代码部分。
第八章 指针
C语言程序设计知识点—第8章 指针结构体与预处理命令
指针使用示例 2 void main() { int num1 = 50, num2 = 100; int *ptr1, *ptr2; ptr1 = &num1; printf(" num1 的值是: %d", *ptr1); printf("\n num1 的地址是: %x \n", ptr1); ptr2 = &num2; printf("\n num2 的值是: %d", *ptr2); printf("\n num2 的地址是: %x \n", ptr2); *ptr2 = *ptr1; printf("\n 重新赋值后 num2 的值是: %d", *ptr2); printf("\n 重新赋值后 num2 的地址是: %x\n", ptr2); }
C 语言程序设计知识点
主讲教师:杨剑
第 8 章:指针、结构体与预处理命令
1. 本章目标
理解指针的概念 定义指针变量 掌握对指针的操作 理解指针和数组的关系 理解结构体的概念和定义 理解预处理指令
2. 内存地址
内存是一个连续编址的空间,每一个存储单元都有一个固定的编号,称为内存地址。 内存地址通常用 16 进制数表示。
C二级 第8章 指针
1.以下定义语句中正确的是A) int a=b=0; B) char A=65+1,b='b';C) float a=1,*b=&a,*c=&b; D) double a=0.0; b=1.1;参考答案:B【解析】A选项语句中b变量还没有定义不能直接用于给a变量赋值。C选项语句中*b、*c表示的是一个实型变量的地址,不能再将&b赋值给指针型变量c。D选项语句中a=0.0后面应该为逗号,不能是分号。2.有以下程序#include <stdio.h>void f(int *p,int *q);main(){ int m=1,n=2,*r=&m;f(r, &n);printf("%d,%d",m,n);}void f(int *p,int *q){ p=p+1;*q=*q+1;}程序运行后的输出结果是A) 2,3 B) 1,3 C) 1,4 D) 1,2参考答案:B【解析】在f(int *p,int*q)函数中,执行p=p+1是将p所对应的地址加1,而*q=*q+1是将q所指向的n的地址所对应的值加1,所以m的得知所对应的值没有变,而n的值则为3了。
因此B选项正确。
3.以下叙述中正确的是A) 如果p是指针变量,则&p是不合法的表达式B) 如果p是指针变量,则*p表示变量p的地址值C) 在对指针进行加、减算术运算时,数字1表示1个存储单元的长度D) 如果p是指针变量,则*p+1和*(p+1)的效果是一样的参考答案:C【解析】B选项中,如果p是指针变量,则*p表示变量p所指向的地址的值;A选项中,如果p是指针变量,则&p表示变量p的地址;D选项中,如果p是指针变量,*p+1表示将p所指的值加上1,而*(p+1)表示的是先将指针右移一位再取所指向变量的值。
因此C选项正确。
4.以下叙述中正确的是A) 基类型不同的指针变量可以相互混用B) 函数的类型不能是指针类型C) 函数的形参类型不能是指针类型D) 设有指针变量为double *p,则p+1 将指针p移动8个字节参考答案:D【解析】B选项中,所谓函数类型是指函数返回值的类型。
C语言程序设计(第3版)何钦铭 颜 晖 第8章 指针
第8章指针【练习8-1】如果有定义”int m, n = 5, *p = &m;”与m = n等价的语句是 B 。
A.m = *p; B. *p = *&n; C. m = &n; D. m = **p;解答:A:p是指向m的指针变量,所以*p等价于m。
即m=m。
B:&n是n的地址,*&n是n的值,即把n的值赋给p指向的值m。
即m=n。
C:&n是n的地址。
即把n的地址赋给m。
D:**p是指p指向的指针所指向的值,在此无意义。
故选B。
【练习8-2】调用函数求两个数的和与差:计算输入的两个数的和与差,要求自定义一个函数sum_diff(float op1,float op2, float *psum, float *pdiff),其中op1和op2是输入的两个数,*psum 和*pdiff 是计算得出的和与差。
解答:#include<>void sum_diff(float op1,float op2,float *psum,float *pdiff);int main(void){float op1,op2,sum,diff;printf("Input op1 and op2: ");scanf("%f%f",&op1,&op2);sum_diff(op1,op2,&sum,&diff);printf("%f+%f=%f;%f-%f=%f \n",op1,op2,sum,op1,op2,diff);return 0;}void sum_diff(float op1,float op2,float *psum,float *pdiff){*psum=op1+op2;*pdiff=op1-op2;}【练习8-3】两个相同类型的指针变量能不能相加为什么解答:不能。
高树芳C语言程序设计--第八章
30
8.5 知识拓展
案例8-11 指针的高级应用 [案例任务] 阅读下列程序 ,分析运行结果,了解指 针的各种应用。
程序代码
31
8.5 知识拓展
相关知识:
1.有关指针的数据类型小结 2.案例说明 3.main函数的参数
32
12
8.2 指针变量
[课堂训练8-1] void swap(int *p1,int *p2) { int *t; t=p1; p1=p2; p2=t; }
1.分析下面的程序,写出运行结果。 #include <stdio.h> void main() { void swap(int *p1,int *p2); int *p1,*p2,a=6,b=8; p1=&a; p2=&b; printf(" 交换前:*p1=%d,*p2=%d\n",*p1,*p2); swap(p1,p2); printf(" 交换后:*p1=%d,*p2=%d\n",*p1,*p2); }
17
8.3 指针与数组
案例8-6 [案例任务]
冒泡排序
使用指针指向一维整型数组,使用冒泡排 序法对数组元素从小到大排序并输出。
程序代码
18
8.3 指针与数组
相关知识: 1.冒泡排序法 2.指针变量的其他运算
19
8.3 指针与数组
案例8-7 [案例任务]
逆置一维数组
使用数组名或指针变量作为函数形参与实 参,完成一维数组元素的逆置。请分析程 序运行结果,并对两个方法进行比较。
6
8.2 指针变量
案例8-2 用指针交换两整数 案例8-3 用指针比较两数大小 案例8-4 用指针参数交换两整数
c语言第8章练习题--指针
1、int *p 的含义是(B)A.p是一个指针, 用来存放一个整型数B.p是一个指针, 用来存放一个整型数据在内存中的地址C.p是一个整型变量D. 以上都不对2、以下函数用来求出两整数之和,并通过形参将结果传回,请填空。
void func(int x,int y, ___int*____ z){ *z=x+y; }3、有如下程序段(B)int *p,a=10,b=1;p=&a; a=*p + b;执行该程序段后,a的值是A. 12B. 11C. 10D. 编译出错4、若己定义:int a[9],*p=a;并在以后的语句中未改变p的值,不能表示a[1]地址的表达式是( C)A) p+1B) a+1C) a++D) ++p5、以下程序运行后的输出结果是(A)void main( ){ int a[ ]={1,2,3,4,5,6,7,8,9,0},*p;for(p=a;p<a+10;p++) printf("%d,",*p);}A)1,2,3,4,5,6,7,8,9,0,B)2,3,4,5,6,7,8,9,10,1,C)0,1,2,3,4,5,6,7,8,9,D)1,1,1,1,1,1,1,1,1,1,6、下面程序的输出是(D)void prtv(int *x)printf("%d\n", ++*x);}main(){ int a=25;prtv(&a);}A) 23 B) 24 C) 25D) 267、有以下函数(B)char fun(char *p){ return p; }该函数的返回值是A) 无确切的值B) 形参p中存放的地址值C) 一个临时存储单元的地址D) 形参p自身的地址值8、下列程序的输出结果是(7)#include<stdio.h>void fun (int *p1, int *p2){ if (*p1>*p2) printf ("%d\n",*p1);else printf ("%d\n",*p2);}void main ( ){ int a=3,b=7;fun (&a, &b);}9、下列程序的运行结果是(B)void fun(int *a, int *b){ int *k;k=a; a=b; b=k;}main(){ int a=3, b=6, *x=&a, *y=&b;fun(x,y);printf("%d %d", a, b);}A) 6 3 B) 3 6 C) 编译出错D) 0 010、以下程序调用findmax函数返回数组中的最大值(B)findmax(int *a,int n){ int *p,*s;for(p=a,s=a; p-a<n; p++)if ( ) s=p;return(*s);}main(){ int x[5]={12,21,13,6,18};printf("%d\n",findmax(x,5));}在下划线处应填入的是(B)A) p>s B) *p>*s C) a[p]>a[s] D) p-a>p-s11、下列程序段的输出结果是(A)void fun(int *x, int *y){ printf("%d %d", *x, *y); *x=3; *y=4;}main(){ int x=1,y=2;fun(&y,&x);printf("%d %d",x, y);}A) 2 1 4 3 B) 2 1 3 4 C) 1 2 1 2 D) 2 1 1 212、以下程序执行后输出的结果是___84________。
第8章 指针
已说明过,且变量类型应与指针类型一致。
可以用一个已赋初值的指针去初始化另一 个指针变量。 不要用一个局部变量去初始化 static 型指针。
4、间接引用指针
与指针有关的两个运算符 & 取地址运算符 * 实例: 指针运算符(或称“间接引用”运算符)
void main(){
int a=10; int *pointer_1; pointer_1 = &a; cout<< * pointer_1;
第
8.1 指针概念
8章
指针
8.5 const指针
8.6 指针与函数
8.2 指针运算
8.3 指针与数组
8.7 字符指针
8.4 堆内存分配
8.9 命令行参数
本章介绍C++的指针。C++语言拥有在运行时获得变量的地址和操作地址 的能力,这种用来操纵地址的特殊类型变量就是指针,指针对于成功地进 行c++语言程序设计是至关重要的。学习本章后要求能够使用指针,能够用 指针给函数传递参数,理解指针、数组和字符串之间的紧密联系,能够声 明和使用字符串数组,正确理解命令行参数。
值。 实例:ch8_9.txt
【 8.5 const指针】
指向常量的指针(常量指针):
在指针定义语句前加上const,表示指向的对象是常量。 不能通过指针来改变所指对象的值,但指针本身可以改 变,可以指向另外的对象。 例: const int a=78;
const int b=28; int c=18; const int *pi=&a; *pi=58; pi=&b; *pi=68; pi=&c; *pi=88; c=98;
08-指针-程序设计基础-罗兵-清华大学出版社
}
被调函数通过指针访问调用函数的局部变量。
8.2 指针与一维数组
一维数组名就是该数组第一个元素的地址,或数组的首地址。 所以将其赋值给一个指针变量后,二者几乎等价,区别是数组名是 指针常量,指针变量是变量,可以再赋值。
int a[]={1,2,3,4},*p;
// 定义数组、指针变量
p=a;
// p为a数组的首地址、整型指针
*(p+i)=*(p+n-1-i); *(p+n-1-i)=m; } }
// 函数定义 // 交换
8.3 指针与二维数组
int a[3][4]; int (*pa)[4]; char **p2; char *(pd[3]);
// 函数声明,a、n均可省略 // 函数声明,p、n均可省略
上面声明的两个函数,它们的参数形式是完全一样的。
8.2.2 指针做函数参数
例8.7 编写函数,将整型数组的元素值逆序。(一维数组名做参数)
void invert1(int a[],int n); { int m,i;
for(i=0;i<n/2;i++) { m=a[i];
指针是一种数据类型,它长度为4字节,它有两重属性:
内存地址 该地址存储数据的数据类型
8.1.2 指针变量的定义
指针类型有指针变量和指针常量。 指针常量不显性表示,通过变量名加取地址运算符、数组名等表示。 指针变量需要先声明,后使用。需要间接寻址运算符 *
int a,b[5]; int *p; p=&a; p=b;
p1=&m;
// p1为变量m的地址、整型
p2=a;
// p2为数组a的首地址、整型
第8章 指针-3字符数组和字符指针 - 字符串的输入和输出
第8章 指针
用scanf输入/输出字符串
#include <stdio.h> #define STR_LEN 80 int main() { char str[STR_LEN+1], ch; printf("Input a string:"); scanf("%s", str); printf("%s\n", str); printf("Input a character:"); getchar(); scanf(" "); ch = getchar(); printf("%c\n", ch); return 0; }
C语言程序设计
第8章 指针
讨论
见证奇迹的时刻——Mission Impossible
源程序(不要添加任何空格和换行) main(){char*a="main(){char*a=%c%s%c;printf(a,34,a,34);}";printf(a,3 4,a,34);} 运行结果与源代码完全一样,你能解释这个运行结果吗? main(){char*a="main(){char*a=%c%s%c;printf(a,34,a,34);}"; printf(a,34,a,34);}
C语言程序设计
gets()将回车从缓冲区读走,但不 作为字符串的一部分,用空字符代替
第8章 指针
用gets输入/输出字符串
#include <stdio.h> #define STR_LEN 80 int main() { char str[STR_LEN+1], ch; printf("Input a string:"); gets(str); printf("%s\n", str); printf("Input a character:"); ch = getchar(); printf("%c\n", ch); return 0; }
C语言程序设计(第3版)何钦铭-颜-晖-第8章--指针
第8章指针【练习8-1】如果有定义”int m, n = 5, *p = &m;”与m = n等价的语句是B 。
A.m = *p; B. *p = *&n; C. m = &n; D. m = **p;解答:A:p是指向m的指针变量,所以*p等价于m。
即m=m。
B:&n是n的地址,*&n是n的值,即把n的值赋给p指向的值m。
即m=n。
C:&n是n的地址。
即把n的地址赋给m。
D:**p是指p指向的指针所指向的值,在此无意义。
故选B。
【练习8-2】调用函数求两个数的和与差:计算输入的两个数的和与差,要求自定义一个函数sum_diff(float op1,float op2, float *psum, float *pdiff),其中op1和op2是输入的两个数,*psum 和*pdiff 是计算得出的和与差。
解答:#include<stdio.h>void sum_diff(float op1,float op2,float *psum,float *pdiff);int main(void){float op1,op2,sum,diff;printf("Input op1 and op2: ");scanf("%f%f",&op1,&op2);sum_diff(op1,op2,&sum,&diff);printf("%f+%f=%f;%f-%f=%f \n",op1,op2,sum,op1,op2,diff);return 0;}void sum_diff(float op1,float op2,float *psum,float *pdiff){*psum=op1+op2;*pdiff=op1-op2;}【练习8-3】两个相同类型的指针变量能不能相加?为什么?解答:不能。
第08章-C++程序设计教程(第3版)(通用版)-钱能-清华大学出版社
指针定义方式
int a=3;
int* p;
//指针定义
int* pa = &a; //指针初始化
指针的意义
从数值的访问走向地址的访问(地址值的数值化) 从访问名字所在存储位置走向访问任何存储位置
获得高效数据访问的同时,也带来数据的不安全性
指针类型
定义时星号前的类型即指针类型 一定类型的指针指向一定类型的实体(如,pa指向a)
过程中不可改
pa = &b;
//b的内存地址表示为&b
cout<<(int)pa; //内存地址不能指定只能读取
cout<<(int)&pa; //指针是存储实体,也有地址
指针值(地址)表现为整数,但指针类型不同,故地址需转换为 整数才能输出或参加其他整数运算
指针类型与实际存储的关系
float f = 34.5;
程序运行中可随机申请一定大小的内存空间(只要有)
字节方式(C方式)
申请: void* malloc(int); 释放: void free(void*); int* p = (int*)malloc(100); //申请需要类型转换 free(p); //释放 将100折算成25个整型实体元素,故p能访问p[0]~p[24]
第8章 指针
8.1 指针概念 8.2 指针运算 8.3 指针与数组 8.4 堆内存分配 8.5 const指针 8.6 指针与函数 8.7 字符指针 8.8 *指针数组 8.9 命令行参数 8.10 函数指针
理解指针以及访问操作 理解指针与数组的关系 理解数组参数传递的指针性质 理解堆内存的申请与释放 理解指针的const修饰 掌握字符指针的操作 掌握命令行参数 学习函数指针的概念
第08章 变量的间接访问——指针 (《程序设计基础(第3版)(C语言)》(王红梅著 清华大学出版社
/*指针p指向变量x */
( 第
int *q = p ;
/*指针q指向变量p所指向的变量x*/
版 )
清
华
x(*p)
大 学
出
x(*p)
p
10
版 社
p
10
q
3
Page 14
8.1 指针的概念 指针变量的初始化
3
int x = 10; double *q = &x;
/*指针q的基类型是double,不能指向int型变量*/
大 学
出
计算机系统和编译器有关。
版 社
(3)定义指针变量时需要明确该指针所指向的数据类型,即该指针所指向的内
存单元可以存放什么类型的数据,对指针变量的运算与它所指向的数据类型密
切相关。
Page 11
8.1 指针的概念
指针变量的初始化
3
例如: int *p ;
int *p = NULL ;
/*NULL为空指针*/
出 版
int *p = NULL, *q = NULL;
/*指针p和q均初始化为空*/
社
p = &x;
/*指针p指向变量x*/
q = p;
/*指针q指向指针p所指内存单元*/
3
Page 17
8.1 指针的概念
指针变量的操作
1. 指针变量的赋值
通常不允许将一个整数赋给指针变量,由于指针的操作需要编程人员保
指针变量的初始化
3
【语法】初始化指针变量的一般形式如下:
基类型 *指针变量名 = 内存地址 ;
程 序 设
计
基
础
【语
义
】定
C语言第8章 指针
例8-13 求最长字符串。
函数的返回值为指针,指针数组作函数参数。
8.5.2 执行函数的指针变量(P207)
P207 自学
8.6 指针应用举例 (P208)
P208 自学
8.7 动态内存管理 (P214)
动态分配存储空间
malloc( )函数 calloc( ) 函数
2. 变量地址示意图
变量 b 的地址:XXXX 变量b 4字节
例: float b; char c;
变量 c 的地址:XXXX 数组 a 的地址:XXXX
变量c 1字节
int a[2];
数组a 8字节
变量的地址示意图
8.1.1 指针和指针变量(P185)
指针
变量的存储地址称为该变量的指针。
指针变量
for (i=0;i<4;i++)
p[i]=&a[i*3]; printf ("%d\n",p[3][2]);
8.4 指针作为函数的参数 (P199)
指针变量 ① 形参是指针变量,对应实参是 变量地址 数组名 指针变量 ② 形参是数组名,对应实参是 变量的地址 数组名
8.4.1 指针作参数示例
例8-10 两数交换。形参为指针变量,实参为变量
char *p="abcd";
读下列程序段,分析输出结果
(1)
char s[]="ABCD";
char *p; for (p=s; p<s+4; p++) printf("%s\n",p);
读下列程序段,分析输出结果
C语言程序设计教程第8章北京邮电大学出版社.
第8章 指针
18
说明: 对于不同基类型的指针,指针变量“加上” 或“减去”一个整数n所移动的字节数(= sizeof( 指针所指对象的数据类型 ) )是不同的。 例如: float a[10], *p=a, *x; x=p+3; /*实际上是p加上3*4个字节赋给x, x依然指向数组的第三个分量*/
C语言程序设计教程
第 8 章 指针
8.1 8.2 8.3 8.4 8.5 8.6 指针与指针变量 指针与函数 指针与数组 指针与字符串 指针数组与命令行参数 程序举例
第8章 指针
2
8.1 指针与指针变量
8.1.1 指针的概念
1.内存与变量地址 内存地址:内存是计算机用于存储数据的存储 器,以一个字节作为存储单元,为了便于访问,给 每个字节单元一个唯一的编号,第一字节单元编号 为0,以后各单元按顺序连续编号,这些单元编号 称为内存单元的地址 。 变量地址:变量所分配存储空间的首字节单元 地址(字节单元编号)。
2018/9/14
C语言程序设计教程
第8章 指针
3
在程序中,对变量的操作实际上是通过地址来完成的。 • 定义时:定义变量→分配内存单元(按类型)→地址 (即内存中的编号) • 存取操作:程序 →变量名 →内存单元 →存取 • 实际上: 程序 →编译 →变量名 →变量的地址
2.访问方式
直接存取:把直接按变量名或地址存取变量值的方式 称为 “直接存取”方式。
2018/9/14
C语言程序设计教程
第8章 指针
10
8.1.3 指针运算
指针运算实际上是地址的计算,包括赋值运算、算术运算、 关系运算三种。
1. 指针的赋值运算 (1)将变量地址值赋给指针变量,使指针指向该变 量。
chap8(指针)
务必记住:*(a+i) 和 a[ i] 是等价的。
如果 a 是一维数组名,则a[ i]代表第 i+1个元素所占的 内存单元。但如果a是二维数组,则a[ i ]代表一维数组名, a[i]本身是不占用内存单元的, 也不存放元素值,而只是 一个地址。 a、a+i、a[ i]、*(a+i)、*(a+i)+j、a[ i]+j都是地址, 而*(a[ i]+j)、*(*(a+i)+j)是二维数组元素a[ i][ j]的值。
二、 字符串指针作函数参数
可以用地址传递的方式,即用字符数组名作 参数或用指向字符串的指针变量作参数,将一个 字符串从一个函数传递到另复制。 用字符数组作参数 void copy_string( from , to ) char from[ ] , to[ ] ; { int i = 0 ; while ( from[i] != „\0‟ ) { to[i] = from[i] ; i + + ; } to[i] = „\0‟ ; 运行结果: } string_a = I am a teacher. string_b = I am a teacher. main( ) {char a[ ] = “I am a teacher.” ; char b[ ] = “you are a student.” ; copy_string( a , b) ; printf( “string_a = %s\nstring_b = %s\n”,a,b); }
形参用字符指针变量 void copy_string(from , to) char *from , *to ; { for ( ; *from != „\0‟; from++; to++) *to = *from ; *to = „\0‟; } main( ) { char *a= “I am a teacher.”; char *b= “you are a student.”; copy_string(a,b); printf( “string_a = %s\nstring_b = %s\n”,a,b) ; }
C语言程序设计(第二版)-电子教案-丁亚涛-8587 第8章 指针
8.5.3 指针与二维数组
• 二维数组其实可以看成由一维数组构造而成。就相当于 几个队列构成一个方阵,方阵由队列组成,队列由具体 的元素--人组成。
• 一级指针只能管理队列,如果管理方阵,则需要二级指 针。
•int a=1000,*pa,**ppa; • pa=&a; • ppa=&pa;
• *(*(ppa)) ≡ *(pa) ≡ a ≡ 1000
• p是二级指针 • *p相当于*(p+0),级别降低为一级指针,相当于p[0] • **p相当于*(*(p+0)+0),级别降低为数组元素(普通变量),
也相当于p[0][0]
• p[1][2],相当于*(*(p+1)+2) • &p[1][2], 级别提升为一级指针,相当于:
• p[1]+2,*(p+1)+2 • &p[1],级别提升为二级指针,相当于:
f=f4; printf("a/b=%d\n",f(a,b));
8.5 指针与数组
• 8.5.1 指针与字符数组 • char str[100]= "Hello World"; • char *p=str; • 字符w可以有如下多种表示形式: • str[6] • *(str+6) • p[6] • *(p+6)
【例8-2】演示指针和数组的关系。
#include <stdio.h>
接可存取,由于p中存储的是x的信息。访问p可以获取x的信 息,再对银行存款进行操作。
8.1 借钱的故事
8.2 指针的概念
• C语言允许使用变量名、数组名[下标]、函数名等标 识符来访问内存
C语言程序设计第八章 指针的使用
第八章指针的使用【学习目标】本章将详细介绍在C语言中如何使用指针。
学习要点包括如下几点:(1)掌握指针和指针变量的概念,了解指针变量的特点以及直接访问数据和间接访问数据的原理。
(2)掌握指针变量的定义、赋值方法及指针运算符的使用,熟练运用指针访问简单变量。
(3)熟悉指针和一维数组的关系,掌握指向一维数组的指针变量的定义方法,熟练使用指针变量访问一维数组元素。
(4)了解指针与字符串的关系,能熟练使用指针处理字符串。
(5)熟练掌握用指针变量作函数的参数时函数的定义和调用方法、数组名作函数的参数用法。
(6)指向指针的指针的运用。
【学习导航】本章的在整个课程中的位置如图5-1所示。
图8-1 本章学习导航在本书的第一章介绍C语言有一个灵活性的特点,那么它的灵活性具体体现在哪里呢?其实就是指针。
指针是C语言的精华部分,通过利用指针,我们能很好地利用内存资源,使其发挥最大的效率。
有了指针技术,我们可以描述复杂的数据结构,对字符串的处理可以更灵活,对数组的处理更方便,使程序的书写简洁,高效。
8.1 地址和指针指针是C语言的一种数据类型,类似于整型、字符型等。
既然指针也是一种类型,那么也可以定义该类型的变量,称为指针变量。
指针变量和其他类型的变量的区别是:指针变量存储的是地址。
所以要学好指针,就一定要明白数据在内存中是如何存储的。
计算机所有数据都是存储在存储器里,系统的内存可看作编了号的小房间,如果要取房间的东西(读取数据)就需要得到房间编号。
地址就是内存区中对每个字节的编号。
下面通过两个整型变量来说明。
整型变量x、y(基本整型需4个字节)在内存中的存储如图8-2所示(假设内存编号是从2000开始)。
把变量所占用的存储单元首字节的地址作为变量的地址。
C语言中利用取地址运算符“&”获取变量的存储地址。
例如,&c将返回c的首地址;&x将返回x的首地址。
2000H2004H2008H2012H...图8-2 变量x和y在内存中的存储图8-2中2000H和2004H就是内存单元的地址。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第八章指针 (2)8.1指针概述 (2)8.1.1理解指针 (2)8.1.2为什么引入指针的概念 (3)8.2指针基础 (7)8.2.1指针变量的声明 (7)8.2.2指针变量的初始化 (7)8.2.3指针变量的赋值 (8)8.3指针编程实例 (10)8.3.1 征婚匹配问题 (10)8.3.2 求解一元二次方程 (12)8.4指针型函数 (14)8.5指针与数组 (17)8.5.1 一维数组与指针 (17)8.5.2指针运算 (18)8.5.3用指针引用数组元素 (19)8.5.4二维数组与指针 (19)8.6指针与数组编程实例 (21)8.6.1 数列的中位数 (21)8.6.2 求矩阵的最大元素 (23)8.7指针与字符串 (24)8.7.1字符型指针、字符数组与字符串常量的概念 (24)8.7.2编程实例判断回文单词和回文句子 (25)8.7.3 C语言字符串操作的库函数 (31)8.7.4 字符串库函数应用实例 (32)8.8常见的编程错误 (34)8.9小结 (37)习题八 (38)第八章指针学习目标⏹理解内存单元的双重属性-内容与地址及其表示方法;⏹理解基本数据类型变量与指针类型变量的异同及其相互关系;⏹学习指针的使用方法:指针初始化,获得变量地址,访问指针所指向的变量;⏹理解指针与数组的关系,学习如何利用指针处理数组;⏹掌握指针作为函数参数及其函数的返回值的作用及其使用方法。
本章我们介绍C语言中的一种新数据类型——指针。
在C语言中,指针被称为派生数据类型,是由基本数据类型衍生而来。
指针的值是内存地址,用指针可以直接访问、操作内存中的数据。
指针是C语言最显著的特点之一,也是C语言最重要的功能,利用指针变量可以方便、灵活地编写C语言程序,解决复杂的编程问题。
例如:指针变量既可以作为函数参数,也可以作为函数返回值,从而使函数有多个返回值;指针提供了另外一种数组处理方法;利用指针可以更方便地处理字符串等。
从本章开始,我们将由浅入深地逐步介绍指针的这些特征。
当然,指针还有其它应用,例如:指针支持动态内存管理,指针可以指向函数,利用指针操作动态数据结构(如链表、队列、栈和树等),有关这些内容我们将在后面章节介绍。
8.1指针概述8.1.1理解指针对于初学者而言,指针有点难以理解。
让我们先看一下计算机内存是如何组织的。
我们已经知道,计算机内存是一系列连续编址(从0开始,1,2,3…依次编号)的内存单元的集合。
通常,内存编址的基本单位为字节,因此,内存中任意字节都有一个特定的地址编码,该地址编码也称为内存地址。
看下面语句:int x=5;该语句指示系统为整形变量x分配存储空间,并把数值5存放在其中。
假设系统为x变量分配的存储空间的内存地址为3000,变量x在内存中的位置可以如图8-1所示。
请注意,图中x占用4个字节的内存(地址3000是该变量所占用内存的首地址),但是有些系统中int型数据占2个字节,请读者自行区分。
可以看出,变量x有两方面属性:一方面是x的地址3000,另一方面是x的值是5。
在C语言中,当我们直接引用x时,我们取的是x的值,对于x的地址,我们需要一种新的数据类型——指针来表示。
假设我们用指针变量p存放x变量的地址,p的值是3000,这样对于内存中的同一个值5,我们有两种方式访问它,可以直接通过变量名x访问,也可以通过指针变量p访问它。
变量x是一个整型变量,而p就是一个指向整型变量的指针,是由整型变量派生的数据类型。
由于变量p 的值是变量x的地址,我们称变量p指向变量x,这就是“指针”名称的由来。
当然,指针变量也是一个变量,需要系统为它分配存储空间,我们可以将变量x和p的值与地址以及二者之间的指向关系表示为图8-2(设系统为变量p分配的内存地址为3100)。
地址 内存单元变量 01 2……3000 x3004 ……图8-1 变量与内存地址 值 变量 3000x3100p图8-2 基本类型变量与指针变量的指向关系刚才我们谈到,当直接引用变量x 时,取的是x 的值属性。
如何表示一个变量的地址属性呢?答案是:在C 语言中用&运算符表示取变量的地址。
例如变量x 的地址可以表示为&x 。
对于指针变量,除了值属性和地址属性以外,还有第三方面的属性,即指向属性。
我们已经知道指针变量的值是另外一个变量的地址,也称指针变量指向另外一个变量。
例如指针变量p 存储变量x 的地址,我们说成p“指向”x ,我们一般不用具体的数值表示地址,而采用简单的图示方法,说明指针p“指向”变量x 。
如图8-3所示:那么,如何使指针变量p“指向” x 呢?我们通过赋值语句p=&x; 来实现。
我们又如何通过指针p 访问x 的值呢?在C 语言中用*(间接寻址)运算符访问指针指向变量的值。
即用*p 来访问x 的值。
程序中x 与*p 是等价的,都代表x 的值5,只不过是x 是直接访问,*p 是间接访问。
8.1.2为什么引入指针的概念从上一节的内容可知,对变量的访问即可以通过变量名直接访问,也可以通过指针间接访问。
既然如此,我们为什么要学习指针呢?因为利用指针变量可以方便、灵活地编写C 语言程序,解决复杂的、利用以前学过的知识难于解决编程问题。
下面我们通过一个例题说明来说明学习指针的重要性,也帮助我们更好地理解指针。
【例8-1】编写一个的子程序,子程序的功能为交换两个变量的值。
程序如下:#include <stdio.h>x图8-3 p“指向”xpvoid swap(int x,int y){int t;printf("交换前:x=%d,y=%d\n",x,y);t=x;x=y;y=t;printf("交换后:x=%d,y=%d\n",x,y);}void main(){int a,b;scanf("%d%d",&a,&b);printf("调用前:a=%d,b=%d\n",a,b);swap(a,b);printf("调用后:a=%d,b=%d\n",a,b);}运行结果:3 5调用前:a=3,b=5交换前:x=3,y=5交换后:x=5,y=3调用后:a=3,b=5Press any key to continue子函数void swap(int x,int y)的功能为交换变量x和y的值。
在主函数中调用swap(a,b)函数后,从运行的结果看,函数并没有实现交换a和b的值的功能,为什么呢?我们将如何实现这一功能呢?在C语言中,函数实参和形参的传递规则是“单项值传递”,即将调用语句中实参赋值给子函数中的形参。
这是一种单向传递方式,子函数的形参得到主调函数的实参值,但在子函数中改变形参的值并不影响主调函数中实参的值。
我们结合图8-4来分析。
图8-4 swap函数调用前后参数变化示意图(1)在主程序中语句swap(a,b);完成子函数的调用,它将实参a、b中的值传递给子函数swap 中的形参x、y,因为C语言的参数传递方式为“单项值传递”,传递后x为5,y为3,见图8-4(a)。
(2)在子程序中执行t=x; x=y; y=t;语句实现了x和y中的值对换,见图8-4(b),我们可以看到x和y的值确实交换了。
(3)当子程序执行执行完毕,程序释放掉形参x、y和局部变量t的存储空间,返回主函数,因此x和y中交换结果也就丢失了。
主函数中变量a、b的值不变,见图8-4(c)。
那么怎样才能实现利用子程序交换两个变量的值呢?这时就要用指针来实现了。
因为C语言的参数传递方式为“单项值传递”,当用简单变量作为函数的参数进行函数调用时,在子函数中对形参的改变不会影响到主调函数中的实参。
我们将形参定义成指针类型swap(int *x,int *y),调用时将变量a和b的地址&a和&b作为实参传递给指针x和y,程序改写为如下形式:源程序:#include <stdio.h>void swap(int *x,int *y){int t;printf("\n-----swap-----\n",x,y);printf("x=%x,y=%x\n",x,y);t=*x;*x=*y;*y=t;printf("-----swap-----\n\n",x,y);}void main(){int a,b;scanf("%d%d",&a,&b);printf("&a=%x,&b=%x\n",&a,&b);printf("调用前:a=%d,b=%d\n",a,b);swap(&a,&b); printf("调用后:a=%d,b=%d\n",a,b); }运行结果: 3 5&a=13ff7c,&b=13ff78 调用前:a=3,b=5-----swap-----x=13ff7c,y=13ff78 -----swap-----调用后:a=5,b=3Press any key to continue我们看到程序的运行结果为a 的值为5、b 的值为3,实现了变量值的交换。
程序的执行过程如图8-5所示:(1)在程序中swap(&a,&b);完成函数的调用,它将变量a 和b 的地址&a 、&b 作为实参递给子函数swap 中的形参x 、y ,其参数传递方式仍为“单项值传递”,因为x 和y 是指针变量,所以传递后指针x 中存放的为a 的地址(13ff7c ),即使x “指向” a ,同理y 中存放的为b 的地址(13ff78),使y “指向” b ,见图8-5(a )。
(2)在子程序中执行t=*x; *x=*y; *y=t;语句,通过指针x 和指针y 的间接访问变量a 和b ,在子程序中执行了将a 的值存入t 中(t=*x ,通过指针x 间接访问a );将b 的值存入a (*x=*y ,通过指针x 间接访问a ,通过指针y 间接访问b );将t 的值存入b 中(*y = t ,通过指针y 间接访问b )实现了a 和b 的值对换,见图8-5(b )。
(3)当子程序执行执行完毕,程序释放掉形参x 、y 和局部变量t 的存储空间,返回主函数,主函数中变量a 、b 的值为交换后的结果,见图8-5(c )。
以上例题只是说明了指针的一个具体应用,利用指针主要可以实现一下应用:main 函数 swap 函数(a) 调用swap 函数(b) 执行swap 函数(c) 从swap 函数返回图8-5 用指针做形参的swap 函数调用前后参数变化示意图(1)指针作虚参可以在子函数中修改实参变量的值。