第8章指针
精品课件-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章 变量的间接访问——指针 (《程序设计基础(第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);
读下列程序段,分析输出结果
TP8
ACCP V4.0
指针使用示例2
内存 void main() { ptr1 num1 int num1 = 50, num2 = 100; 12ff7c 50 int *ptr1, *ptr2; ptr1 = &num1; 12ff7c printf(" num1 的值是: %d", *ptr1); ptr2 num2 printf("\n num1 的地址是: %x \n", ptr1); 12ff78 ptr2 = &num2; 50 100 printf("\n num2 的值是: %d", *ptr2); 12ff78 printf("\n num2 的地址是: %x \n", ptr2); *ptr2 = *ptr1; printf("\n 重新赋值后 num2 的值是: %d", *ptr2); printf("\n 重新赋值后 num2 的地址是: %x\n", ptr2); }
arr_num[0] arr_num[1] arr_num[2] arr_num[3] arr_num[4] arr_num[5] arr_num[6] arr_num[7]
41 60
23 15 60 41 49 13 39
14
ACCP V4.0
指针关系运算
比较两个指针
#include<stdio.h> void main () { int *ptrnum1, *ptrnum2; int value = 1; ptrnum1 = &value; value += 10; ptrnum2 = &value; if (ptrnum1 == ptrnum2) printf("\n 两个指针指向同一个地址\n"); else printf("\n 两个指针指向不同的地址\n"); }
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)。
值传递:callByValue()
#include <stdio.h> int callByValue(int); /*返回参数的立方*/ void main() { int number = 5; printf("The original value of number is %d", number); number = callByValue(number); printf("\nThe new value of number is %d", number); } int callByValue(int n) { return n*n*n; } The original value of number is 5 The new value of number is 125
指针
指针运算
指针可以参与以下运算:
赋值运算
给指针变量赋值
关系运算
两个指针之间的比较
算术运算
加(减)一个整数 两个指针相减
18
指针
指针运算
指针的赋值运算
可以把指针赋给同类型的指针变量。
int x=10, *p, *q; p = &x; p 2000 x 10 2000
q = p;
printf(“*q=%d", *q); *q=10
vP1 vP2
?vP1 + 2
2000 + 2 = 2002
2000 + 2*2 = 2004
2000 2002 2004 2006
数组 v
所指向的内存对象 的长度
23
指针
指针运算
指针的算术运算
举例
int *vP1, *vP2; vP1 = (int*)2000; vP2 = (int*)2004; vP1 vP2
The value of a is 7 The value of *aPtr is 7
Showing that * and & are inverses of each other. &*aPtr = 1A58 *&aPtr = 1A58 * 和 & 是互反的
12
指针
指针作为函数的参数
指针作为函数的参数用来模拟引用传递。
aPtr = &a;
printf("The address of a is %p"
"\nThe value of aPtr is %p", &a, aPtr); printf("\n\nThe value of a is %d" "\nThe value of *aPtr is %d", a, *aPtr);
结果分析
调 用 前 void main() { number 5 int number = 5; callByReference(&number); } void main() { 125 number int number = 5; callByReference(&number); } void main() { 125 number int number = 5; callByReference(&number); }
3
指针
指针的概念
指针就是内存对象的地址。
内存对象包括:变量,数组,函数等。 C语言允许直接通过地址来处理数据。
int x; x=23; 直接引用
Direct reference 通过变量名直接引用 变量占用的内存单元。
FF00
内存单元的地址 一个无符号的整数, 就是指向变量的指 针。
23
x
变量名 其实就是内存 单元的符号化 名称。
function
5
指针
指针变量
指针变量就是保存内存地址的变量。
int x=23; 间接引用
Indirect reference
int *x_pointer;
x_pointer=&x;
通过指针变量间接引用 变量占用的内存单元。
指针变量
FF00
23
x
•保存变量的地址。 •变量 x_pointer 的值是变量 x 的地址(指针)。 •目前,指针 x_pointer 指向变 量 x 。
void callByReference(int *nPtr) { *nPtr = *nPtr**nPtr**nPtr; } The original value of number is 5 The new value of number is 125
15
指针
案例分析:指针参数
问题:计算任意整数的立方。
int x, *p=(int *)0xffe;
强制类型转换
8
指针
取地址运算符
取地址运算符:&
返回变量在内存中的地址。
int y, *yPtr; y = 5; yPtr = &y;
yPtr
y 5
yPtr
yfΒιβλιοθήκη f0ff00ff00
5
yPtr “指向” y
y的地址是yPtr的值
9
指针
指针运算符
指针运算符:*
14
指针
案例分析:指针参数
问题:计算任意整数的立方。
值传递:callByReference()
#include <stdio.h> void callByReference(int*);
void main() { int number = 5; printf("The original value of number is %d", number); callByReference(&number); printf("\nThe new value of number is %d", number); }
将 bPtr 的值置为数组 b 中的第一个元素的地址 bPtr = b; 等价于 bPtr = &b[0];
25
指针
指针与数组
数组和指针关系密切。
引用数组元素的表达式
数组元素 b[3] 可以用 *(bPtr + 3) 来引用
– 3是偏移量 – 这种表示法称为指针偏移量表示法
还可以用 bPtr[3] 来引用
q
2000
19
指针
指针运算
指针的赋值运算
把指针赋值给类型不同的指针变量时要进行类型转换。
int a, *intPtr=&a; char *charPtr;
charPtr = (char*)intPtr;
但 void * 类型的指针是一个例外。
int a, *intPtr=&a; char *charPtr;
– 称为指针下标表示法 – 与 b[3] 相同
还可以用 *(b + 3) 来引用
26
指针
指针与数组
数组和指针关系密切。
引用数组元素的表达式
main() { int i, a[5]={1,2,3,4,5}; for (i=0; i<5; i++) printf("%2d",a[i]); }
下标法
内存单元的内容 就是变量的值。
4
指针
内存对象的地址
变量的地址
用取地址运算符(&)获得变量在内存中的地址。
int var; scanf(“%d”, &var);
var
数组的地址
即第一个元素的地址,用数组名表示。
int array[3];
array
函数的地址
用函数名表示。
int function(int x);
用指针变量作为函数的形式参数。
int myFunc( int *ptr );
调用函数时,用 & 运算符把实际参数的地址传递给函数。
myFunc( &var );
在被调用函数中,用 * 运算符间接引用实际参数。
int myFunc( int *ptr ) { *ptr = … }
13
指针
案例分析:指针参数
void callByReference(int *nPtr) { *nPtr = *nPtr**nPtr**nPtr; } nPtr
调 用 时
void callByReference(int *nPtr) { *nPtr = *nPtr**nPtr**nPtr; } nPtr
调 用 后
void callByReference(int *nPtr) { *nPtr = *nPtr**nPtr**nPtr; } nPtr
– 0 和 NULL 是等价的(用NULL更好) – NULL 是在<stdio.h>(和几个其他头文件)中定义的符号常量
int x, *p=NULL; 空指针:不指向任何对象
int x, *p=&x; int x, *p=0xffe;
Warning: Nonportable pointer conversion
?vP2 - vP1
=2
vP2和vP1之间内 存对象的个数
2000 2002 2004 2006
数组 v
指针的算术运算在 数组上使用才有意 义
24
指针
指针与数组
数组和指针关系密切。
数组名是一个指针常量。 数组指针:指向数组的指针。 数组指针可以用来完成任何涉及数组下标的操作。
int b[5]; int *bPtr;
p1 p2
2000 2002
char *charPtr; …