7.指针
- 格式:pdf
- 大小:337.48 KB
- 文档页数:78
指针的名词解释指针是计算机编程中常用的一种数据类型,它存储了内存中某个变量的地址。
通过指针,我们可以间接地访问和修改内存中的数据,进而实现复杂的计算和数据处理。
1. 指针的定义和声明指针变量是一种特殊的变量,其存储的值是另外一个变量的地址。
我们可以通过将变量名前面加上一个"*"符号来声明指针变量。
例如,int* p; 表示声明了一个名为p的整型指针变量。
2. 指针与内存地址的关系每个变量都存储在计算机的内存中,并被赋予一个唯一的地址。
指针变量存储的值就是某个变量的地址,通过指针,我们可以直接操作和访问内存中的数据。
这种直接访问内存地址的方式,赋予了指针在编程中非常重要的地位。
3. 指针的应用指针在编程中起到了非常重要的作用,它们广泛应用于各种算法和数据结构中。
以下是指针的几个常见应用:a. 动态内存分配:通过指针可以在程序运行时动态地分配和释放内存。
这种灵活性可以大大提高程序的效率和资源利用率。
b. 数据结构中的指针:指针在链表、树等数据结构中扮演着重要的角色。
通过指针的相互连接,我们可以实现复杂的数据结构和算法。
c. 函数与指针:指针可以作为函数的参数来实现数据传递和共享。
通过传入指针,函数可以直接修改调用者传递的变量,实现更加灵活的数据处理。
d. 指针与数组:数组名本身就是指向数组首元素的指针。
通过指针,我们可以方便地对数组进行遍历和操作,提高了数组的处理效率和灵活性。
4. 指针的注意事项指针在编程中具有强大的功能,但也有一些需要注意的地方:a. 空指针:指针的值可以是空,即指向内存地址为0的情况。
使用指针前,最好先判断其是否为空,以免引起程序的崩溃或意外行为。
b. 野指针:指针变量必须在初始化后才能使用,否则可能会指向无效的内存地址。
使用指针前,务必确保其已正确初始化,避免野指针的问题。
c. 内存泄漏:动态分配的内存需要手动释放,否则会造成内存泄漏。
在不需要使用某块内存时,及时释放它,以避免浪费和程序性能下降。
实验七:指针的应用【实验目的】1.掌握指针和指针变量,内存单元和地址、变量与地址、数组与地址的关系;2.掌握指针变量的定义和初始化,指针变量的引用方式;3.能正确使用数组的指针和指向数组的指针变量;【实验内容】1.填空题输入一个字符串,将其中的大写字母转换成小写字母,然后输出本程序主要是比较scanf()输入和gets()输入的区别#include <stdio.h>void main(){ char s[20];char *p=s;scanf(“%s”,p); /*注意用scanf()输入和gets()输入的区别*/while( 1 ){if( 2 ) *p=*p+ (‘a’-‘A’);p++ ;}puts ( 3 );}答案:1、*p!=’\0’2、(*p>='A')&&(*p<='Z')3、s运行结果:输入:Program输出:program输入:This is Program输出:this提示:scanf ()输入时遇到空格认为字符串结束,用gets()输入时只有遇到回车才认为字符串结束。
如键入any boy并回车,则2。
补充程序题输入15个整数存入一维数组,再按逆序重新调整该数组中元素的顺序然后再输出。
下面给出部分程序的内容,请将程序补充完整,然后上机调试。
部分程序清单如下:#include <stdio.h>void main(){ int a[15],*p1,*p2,x;for(p1=a;p1<a+15;p1++)scanf("%d",p1);for(p1=a,p2=a+14;p1<a+7;p1++,p2--){ x=*p1;*p1=*p2;*p2=x;}……}答案:for(p1=a;p1!=a+15;p1++)printf("%d ",*p1); // %d后面有一个空格运行结果:输入:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15输出:15 14 13 12 11 10 9 8 7 6 5 4 3 2 1提示:(1)在整型数组中,没有结束标志,必须依靠数组中数据元素的个数控制循环次数。
C语⾔教材第七章指针实验第七章指针第⼀部分知识训练【知识要点】1. 地址与指针指针变量的概念:⽤⼀个变量专门来存放另⼀个变量的地址。
2. 指向变量的指针变量指针变量的形式:基类型 *指针变量名;&: 取地址运算符;*:指针运算符。
3. 指针与数组引⽤⼀个数组元素可以⽤下标法和指针法;可以⽤数组名作函数的参数。
4.指针与函数函数指针变量定义的⼀般形式为:类型说明符 (*指针变量名)();⼀个函数的返回值可以是⼀个函数。
【典型习题与解析】5. char * const p;char const * pconst char *p上述三个有什么区别?【解析】char * const p; //常量指针,p的值不可以修改;char const * p;//指向常量的指针,指向的常量值不可以改;const char *p; //和char const *p。
6. main(){int a[5]={1,2,3,4,5};int *ptr=(int *)(&a+1);printf("%d,%d",*(a+1),*(ptr-1));}输出结果是什么?【解析】答案:输出:2,5*(a+1)就是a[1],*(ptr-1)就是a[4],执⾏结果是2,5。
&a+1不是⾸地址+1,系统会认为加⼀个a数组的偏移,是偏移了⼀个数组的⼤⼩(本例是5个int)。
1)&a是数组指针,其类型为 int (*)[5];⽽指针加1要根据指针类型加上⼀定的值,不同类型的指针+1之后增加的⼤⼩不同。
2)a是长度为5的int数组指针,所以要加 5*sizeof(int),所以ptr实际是a[5],但是prt与(&a+1)类型是不⼀样的(这点很重要),所以prt-1只会减去sizeof(int*) a,&a的地址是⼀样的,但意思不⼀样。
3)a是数组⾸地址,也就是a[0]的地址,&a是对象(数组)⾸地址,a+1是数组下⼀元素的地址,即a[1],&a+1是下⼀个对象的地址,即a[5]。
c语言的7种数据类型C语言是一种广泛使用的编程语言,在C语言中有7种基本的数据类型,分别为:整型、浮点型、字符型、布尔型、指针类型、数组类型和结构体类型。
下面将对每种数据类型进行详细介绍。
1. 整型(int):整型用于表示整数,它可以分为有符号整型和无符号整型。
有符号整型可以表示正数、负数和零,而无符号整型只能表示非负数。
在32位操作系统下,有符号整型的取值范围为-2^31到2^31-1,而无符号整型的取值范围为0到2^32-1。
2. 浮点型(float和double):浮点型用于表示带有小数部分的数字。
C语言提供了两种浮点类型:float和double。
float类型在内存中占用4个字节,而double类型在内存中占用8个字节。
它们的取值范围和精度不同,double类型的取值范围和精度比float类型更大。
3. 字符型(char):字符型用于表示单个字符,它是基本的文本数据类型。
char类型在内存中占用1个字节,可以表示256个不同的字符。
在C 语言中,字符型变量使用单引号来表示,如:'A','0'等。
4. 布尔型(bool):布尔型用于表示真或假的值。
在C语言中,布尔类型是通过预处理指令#define来定义的,可以使用true和false关键字来表示真和假。
5. 指针类型(pointer):指针类型用于存储变量的内存地址。
在C语言中,使用指针可以实现对内存的直接访问和操作。
指针类型在内存中占用4个字节或8个字节,取决于所在的操作系统。
6. 数组类型(array):数组类型用于存储一系列具有相同数据类型的元素。
在C语言中,数组可以是一维的,也可以是多维的。
数组的长度在定义时就需要确定,并且无法改变。
7. 结构体类型(struct):结构体类型用于自定义复杂的数据类型。
结构体是一种可以包含多个不同数据类型的数据类型,它可以将不同的数据组合在一起,形成一个逻辑上的整体。
第七部分 指针7.1 选择题1. 若有说明:int a=2, *p=&a, *q=p;,则以下非法的赋值语句是()。
A . p=q;B . *p=*q;C . a=*q;D . q=a;2. 若定义:int a=511, *b=&a ;,则printf("%d\n ", *b);的输出结果为:A . 无确定值B . a 的地址C . 512D . 5113. 已有定义 int a=2, *p1=&a, *p2=&a; 下面不能正确执行的赋值语句是()。
A . a=*p1+*p2;B . p1=a;C . p1=p2;D . a=*p1*(*p2);4. 变量的指针,其含义是指该变量的()。
A . 值B . 地址C . 名D . 一个标志5. 若有说明语句:int a, b, c, *d=&c ;,则能正确从键盘读入三个整数分别赋给变量a 、b 、c 的语句是()。
A . scanf("%d%d%d ", &a, &b, d);B . scanf("%d%d%d ", a, b, d);C . scanf("%d%d%d ", &a, &b, &d);D . scanf("%d%d%d ", a, b,*d);6. 若已定义int a=5; 下面对(1)、(2)两个语句的正确解释是()。
(1) int *p=&a; (2) *p=a;A . 语句(1)和(2)中的*p 含义相同,都表示给指针变量p 赋值。
B . (1)和(2)语句的执行结果,都是把变量a 的地址值赋给指针变量p 。
C . (1)在对p 进行说明的同时进行初始化,使p 指向a ;(2)变量a 的值赋给指针变量p 。
D . (1)在对p 进行说明的同时进行初始化,使p 指向a ;(2)将变量a 的值赋予*p 。
C语言中级3 Sept. 2008©Neusoft Confidential第七章:指针目标:1)指针的用途2)掌握二级指针的正确使用3)掌握指针数组的正确使用4)熟悉函数指针的使用5)掌握各式各样的指针的识别6)独立完成作业题时间:学时教学方法:PPT+实验指针到底有什么好处?好处太多了,比如:提高程序效率(高效地传递数组和结构,指针偏移可以指向任何数组元素或者任何数据结构的成员)。
实现动态数组,对多个相似变量的一般访问(模拟数组)。
实现各种动态分配的数据结构。
“好坏参半”的指针指针是“神通广大的特权者”,它不受约束,可以访问任意内存。
p= &a;//变量a的地址;p = A;//数组名A;p = q;//指针q;p = fun;//函数名fun;p = NULL;//NULL;最能体现C的灵活性,但也给程序埋下了隐患。
甚至也有人说指针“好坏参半”,的确如果使用不当,特别是赋予了它一个错误的值时,会成为一个机器隐蔽的、难以发现和排除的故障。
所以要慎重的使用指针。
0013FF780013FF7C0013FF800013FF840013FF880013FF8C0013FF900013FF9410地址内存内存中每一个字节有唯一编号,这就是“地址”。
变量的访问方式:(1)直接访问──使用变量名进行存取。
(2)间接访问──通过该变量的地址来访问。
*(int *)(0x0013FF78) = 10;7.1指针的概念地址编号不容易记忆,访问不方便。
7.1 指针的概念指针是用来存放其它变量地址的变量(且只能存放地址)。
是一种特殊形式的变量。
特殊在哪儿?其value是别人的地址;可以定义为void *间址访问才有意义。
指针是C语言提供给编程者符号化使用“难记忆的”硬件地址的一种方法。
7.1 指针的概念-误区1.有人说:“指针就是地址!”对吗?为什么?2.数组名是什么?指针是一种容纳地址的变量,通常也叫指针变量,统称指针。
而地址则是内存单元的编号,是一个常值。
指针绝对不等同于地址,千万不要把二者意义混淆。
数组名是常地址7.2 指针的定义方式类型*指针变量名;定义了指针变量之后,它只能指向同一个类型的变量。
以下定义,pb是指针吗?1) char* pa,pb;2) char*pa,pb;pb若为指针,应该写成:char*pa,*pb;或者:char *pa;char *pb;推荐写成后一种写法。
&:取址运算符(※只能作用于变量)。
*:指针运算符(间接访问运算符),或指针定义符。
示例1:int main(){int i = 0;int *p = &i; //此处*为指针定义符*p = 10;//此处*为指针运算符,访问i变量return 0;}“*”又叫间接访问运算符,说明是通过指针变量去间接访问指针所指变量。
对*运算符的误解:int i = 0;int *p = &i;//指针定义*p = 10;//指针的使用,*p 仅仅代表着i的值吗?错!*p 代表i变量本身,可做左值7.3和指针有关的运算符以下两个例子可以等效为什么样子的语句?示例1:int x = 0,y = 1; int *px = &x; y = *px;示例2:int x = 0,y = 1; int *px = &x; *px = y;<==> y = x; <==> x = y;※使用指针变量之前确保该指针变量指向一个合法可用的内存单元。
错误示例1:int main( ) {int *p;*p = 1;}错误示例2:int main( ){int *p = NULL; *p = 1;}指针变量与零值比较的问题#define NULL ((void *)0)你会这么写吗?if( p == NULL )可以,但是不好,应该这么来写:if( NULL == p )指针有以下几种运算:赋值、*运算、&取地址、加/减一个整数、自增/减、求差、比较。
指针可以进行的算术运算,只有以下几种:p±n, ++p/p++, --p /p--, p1-p2思考:p±n, p1-p2用途?//见后页练习7.4 指针的使用练习1 //请解释红色问号处的结果void main( ){int a[10] = {1,};int *p = &a[1];int * r;int i, j;int *q = &a[4];r = p+2;//?i = q-p;//?j =&a[1]-&a[0];// ?}7.4 指针的使用练习1结论p±n:将指针从当前位置向前(+n)或回退(-n)n个数据单位(指针指向的类型),而不是n个字节。
显然,++p/ p++和--p/p--是p±n的特例(n=1)。
p1-p2:两指针之间的数据个数,而不是指针的地址之差。
7.4 指针的使用练习2:指出各题错误1. int i,*p;p = i;2. char *p,*q,*r;r = (p + q) / 2;3. int *ipt;float *fpt;if(ipt > fpt){ }7.4 指针的使用练习3滑稽的陷阱int main(){int i = 5;int j = 10;int *p = &i;int result;result = j /*p;return 0;}int i = 20;int *pi = &i; int **ppi = π指针变量ppi地址2变量i值指针变量pi地址17.5多级指针二级指针:指向指针的指针7.5 多级指针—为什么要使用它?示例1:下面程序功能申请一块空间有什么问题?(为了简化篇幅,省略malloc是否分配成功的处理) void getspace(char *pi){pi = (char*)malloc(10*sizeof(int));}int main(){int i = 0;char *p = NULL;getspace (p);for(i = 0;i<10;i++)p[i] = i;}7.5 多级指针示例1改正如下void getspace (char **pi){*pi = (char*)malloc(10*sizeof(int));}int main(){int i = 0;char *p = NULL;getspace (&p);for(i = 0;i<10;i++)p[i] = i;}本题只有经过传递指针变量的地址才可以使指针指向开辟的堆空间示例2:能否得到打印hello ?//1.c#include <stdio.h>extern void fun(char **p);void main(){char *p = NULL;fun (&p);printf("%s\n", p);}7.5多级指针//2.cstatic const char *pstr = "hello";//指针pstr 只可以本文件访问void fun (const char **p)//接口函数{*p = pstr;}能打印。
1、通过传递指针变量的地址使得主调函数中指针变量被改变2、通过合理的使用二级指针可以使变量访问更安全7.5多级指针—误区不要把多级指针和指向数组的指针定义混淆:char **p1;char (*p2)[5];char *p3 [5];p1是二级指针,p2、p3级别等效为二级指针。
一个小试验:main(){char **p1;char a[10][5];char(*p2)[5] = a; p1 = a;//查看p1+1和p2+1}实验证明:可以让一个指向一维数组的指针去模拟二维数组的行为,把二维数组看成由大元素构成的一维数组。
指向一维数组的指针和普通二维数组可以在一起使用。
是普通二级指针是指向char [5]数组的指针。
是以char* 为基本元素类型的指针数组7.6.1指针数组定义int *a[10];//定义了一个一维指针数组,特殊在每个元素都是指针。
int **p = a;a+1和p+1的结果是多少?结论:可让一个二级指针指向一维指针数组。
二级指针和一维指针数组可以在一起使用。
课前提问说出以下变量的含义以及偏移“1”走的距离:int a[4][5]; //a+1?int (*p1)[5];//p1+1?int **p2;//p2+1?int *p3[5];//p3+1?可以让指针p1获得数组a的首地址,进而访问二维数组的各个元素,可以让p2获得指针数组p3的首地址,进而访问指针数组各个元素7.6.2 指针数组的应用字符串由小到大排序(字典顺序):将字符串“yellow”,“red”,“green ”,“blue”排序后显出来,排序后结果为“blue”,“green”,“red ”,“yellow ”字符串排序,法1:使用普通的二维数组,程序见后页char color[4][7] = {“yellow",“red"," green "," blue "};y e l l o w \0r e d \0g r e e n \0blue\0color[0]color[1]color[2]color[3]int main(){char color[4][7] = {"yellow", "red","green","blue"};char temp[7];int i= 0;int j = 0;for(i=0; i<3; ++i)for(j=0; j<3-i; ++j){if (strcmp(color[j],color[j+1]) > 0){strcpy(temp,color[j]);strcpy(color[j],color[j+1]);strcpy(color[j+1],temp);}}for(i = 0;i <4;++i){printf("%s\n",color[i]);}}用二维数组储存字符串。
缺点:1.浪费空间2.排序需要改变字符串的位置,要多次使用strcpy 效率较低。
b l u e \0\0g r e e n\0r e d \0yellow7.6.2 指针数组的应用y e l l ow\0r e d \0g r e e n \0blue\ore d \0\0y e l l o wbl u e \0g reen\0C[0]C[1]C[2]C[3]red\0\0y e l l o wblue\0green\0C[0]C[1]C[2]C[3]字符串排序,法2:使用指针数组,程序见后页char* color[] = {"red","yellow","blue","green"};#include<string.h>#include <stdio.h>int main(){char* color[] = {"red","yellow","blue","green"};char *temp;int i= 0;int j = 0;for(i=0; i<3; ++i)for(j=0; j<3-i; ++j){if (strcmp(color[j],color[j+1]) >0){temp = color[j];color[j] = color[j+1];color[j+1] = temp;}}for(i = 0;i <4;++i){printf("%s\n",color[i]);}}使用指针数组排序优点:1. 占用空间小。