前言
指针是C语言中的一个重要概念及其特点也是掌握 C语言比较困难的部分。 指针也就是内存地址 ,指针变量是用来存放内存地址的变量,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的 存储空间 长度也不同。 有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。
一.指针概念
1.1 指针的类型
去掉指针本身剩下的就是指针的类型
- intptr;//指针的类型是int
- charptr;//指针的类型是char
- intptr;//指针的类型是int
- int(ptr)[3];//指针的类型是int()[3]
- int*(ptr)[4];//指针的类型是int(*)[4]
1.2 指针所指向的类型
去掉指针本身和指针前面的*剩下的就是指针所指向的类
- int*ptr; //指针所指向的类型是int
- char*ptr; //指针所指向的的类型是char
- int*ptr; //指针所指向的的类型是int
- int(*ptr)[3]; //指针所指向的的类型是int()[3]
- int*(ptr)[4]; //指针所指向的的类型是int()[4]
1.3 指针的值
指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。在32 位程序里,所有类型的指针的值都是一个32 位整数,因为32 位程序里内存地址全都是32 位长。64位也是如此,在64位程序中,所有类型的指针的值都是64位整数。指针所存储的值是地址。
1.4 &和*
- &:&在指针运算中为取地址符号
- *** :** *在指针运算中为获取地址所指向内存单元的值的符号
int* p; //定义指针 |
&*p和*&p的区别:
因为*和&具有相同的优先级,且是右结合性(从右向左),故分析可得:
1)&*p:相当于&(p),首先进行一次p运算再取地址。若p是一个非指针变量,p是非法的;若p是一个指针变量,&(p)=p;
2)*&p:相当于*(&p),先取地址再做*运算。若p是一个非指针变量,(&p)=p;若p是一个指针变量,(&p)=p。
1.5 指针的运算
对于指向数组的指针变量,可以加上或减去一个整数n,这意味着把指针从当前指向的位置(指向的某个数组元素)向后或向前移动n个位置。
这里应当注意:
(1)数组指针变量向前向后移动一个位置和地址加1或减1在概念上是不同的。因为数组的元素可以由不同的数据类型,所占用的字节长度也是不同的。如指针变量加1,即表示指针变量指向下一个元素的首地址,而不是在原地址的基础上加1;
(2)指针变量的加减运算只能对数组指针变量进行,对只想其他数据类型的指针变量做加减运算是毫无意义的。
(3)两个指针变量之间的运算:只有指向同一数组的两个指针变量才能进行运算,否则运算是毫无意义的。
(4)两指针变量相减:两指针变量相减所得之差,是两个指针所指向的数据元素之间相差的元素个数,乘以该数组每个数据元素的长度(字节数);
(5)两指针变量相加:两指针变量不能进行加法运算,毫无实际意义。
int*p; //p所指向的类型为int类型 |
char* p1; //p1所指向的类型为char类型 |
二.指针与一维数组
2.1 一维数组
2.1.1 一维数组的初始化
(1)在定义数组时对所有数组元素赋初值
int data[5]={100,99,98,97,95}; |
(2)对数组部分元素赋初值
int data[5]={100,99}; |
将100、99赋给data[0]、data[1],其余数组元素自动赋值0。
(3)对全部数组元素赋处置,省略数组长度
int data[]={100,99,98,97,95}; |
将初值依次赋值给数组的各个元素,数组长度由初值个数决定。
三.指针与二维数组
3.1.1 二维数组的初始化
(1)按行给二维数组初始化
int socre[4][3]={{99,98,97},{96,95,94},{93,92,91},{90,89,88}} |
99 | 98 | 97 |
---|---|---|
96 | 95 | 94 |
93 | 92 | 91 |
90 | 89 | 88 |
(2)按排列数序初始化
int score=[4][3]{99,98,97,96,95,94,93,92,91,90,89,88} |
(3)对部分元素赋初值
int socre[4][3]={{99,98},{96,95,}} |
对二维数组进行赋值,为赋初值的数组元素,系统自动赋值为0
(4)初始化时省略第一维长度
int socre[][3]={{99,98},{96,95,}} |
3.2 二维数组与指针
3.2.1 二维数组与指针的关系
在c语言中,二维数组可以看作是一维数组的嵌套而构成的,一个二维数组可以按行分解成多个一维数组。例如,有如下定义:
int a[3][4]; |
二维数组a可分解为三个一维数组,其数组名分别为a[0],a[1],**a[2]**。每个一维数组有四个元素。
c语言规定数组名代表数组的首地址,因此a[i]是第i行第0列的数组元素(a[i][0])的地址,即a[i]与&a[i][0]等价,即a[i]+j就是第i行第j列的数组元素a[i][j]的地址,即a[i]+j与&a[i][j]等价。所以对于二维数组a有以下关系:
a[i]+j等价于&a[i][j] |
根据一维数组与指针的关系可知:a[i]等价于*(a+i),进而可推出二维数组与指针的关系:
(1)*(a+i)+j等价于&a[i][j] |
3.3 数组指针
**数组指针:**指向数组的指针。
int(*p)[i]; |
首先要明确优先级顺序:()>[]>*
(* p)[n]:根据优先级,先看括号内的,p是一个指针,指向一个一维数组,数组的长度是n,这是指向数组的指针,叫做数组指针。
指针的类型为int(*)[i],指针所指向的类型为int()[i],在运行p+1时,p所指向的地址在原有的地址上增加sizeof(int)*i。
编辑
3.4 指针数组
指针数组:装着指针的数组。
int* p[4]; |
p[n]:根据优先级,先看[],则p是一个数组,再结合,这个数组的元素是指针类型,共n个元素,是装着指针的数组,叫做指针数组。
编辑
指针数组++是指将指向指针数组第一个元素的指针向后移动一个元素的位置。具体来说,如果有一个指针数组p
,其中包含n个指针,每个指针指向不同的内存地址,那么p++
将把指针向后移动一个元素的位置,即指向p[1]
的指针。如果再执行p++
,则指针将指向p[2]
,以此类推。
3.5 指针数组和数组指针
指针数组和数组指针是两个不同的概念。
指针数组是一个数组,其中的每个元素都是一个指针,每个指针指向不同的内存地址。例如,int *ptrArr[10]
定义了一个包含10个指向int类型的指针的数组,每个指针都可以指向不同的int类型变量。
数组指针是一个指针,它指向一个数组的首地址。例如,int (*arrPtr)[10]
定义了一个指向包含10个int类型元素的数组的指针。在这种情况下,arrPtr
指向的是整个数组,而不是数组中的一个元素。
因此,指针数组和数组指针的本质区别在于它们的类型不同,一个是数组,一个是指针。指针数组中的每个元素都是一个指针,而数组指针指向的是一个数组。在使用时需要根据具体情况选择合适的类型。
问题:指针数组名到底是数组名还是指针名?
指针数组名既可以被视为指针名,也可以被视为数组名,具体取决于它的上下文环境。
在指针数组作为函数参数传递时,指针数组名被视为指针名。因为在函数调用时,指针数组会被转换为指向其首元素的指针,并传递给函数。因此,指针数组名被视为指向数组首元素的指针名。
例如,下面的函数原型中,ptrArr
被视为指向数组首元素的指针名:
void func(int *ptrArr[], int len); |
在指针数组被定义时,指针数组名被视为数组名。因为指针数组本质上是一个数组,指针数组名表示整个数组。在定义指针数组时,需要指定数组的长度,这个长度就是数组的元素个数。
例如,下面的定义中,ptrArr
被视为数组名:
int *ptrArr[10]; |
因此,指针数组名既可以被视为指针名,也可以被视为数组名,具体取决于它的上下文环境。
四.指针与字符串
4.1 字符数组
对字符数组的初始化有以下几种情形
(1)和其他数组一样,对字符数组逐个初始化
char str[5]={'a','b','c','d','\0'}; |
注意:c语言规定以字符’\0’作为字符串的结束标志。如果没有’\0’,只能说数组str中存储了一串字符,但不能说str存储了字符串。
(2)用字符串直接初始化字符数组
char str[6]={"hello"}; |
编译器将双括号括起来的字符依次赋值给字符数组的各个元素,并自动在末尾补上字符结束标志字符’\0’,一起存在数组str中,所以数组的个数要比字符串中字符的个数要多一个。在输出字符串时,末尾’\0’不输出,只用于判断字符串是否结束。
char str[]="hello"; |
按这种方式定义和初始化字符串数组,不必指定数组的大小,编译系统会根据字符串中字符的个数确定数组的大小。由于字符串常量”hello”的末尾字符时’\0’,因此字符数组的长度为字符串的额中世纪的个数加1,即:字符数组str的长度为6。
4.2 字符指针
字符指针时指向字符型数据的指针变量。每个字符串在内存中都占用一段连续的存储空间,并有唯一的首地址。因此,只要把字符串的首地址赋值给字符指针,即可让字符指针指向字符串。
char* p; |
五.指针函数与函数指针
5.1 指针函数
1.指针函数的概念
指针函数是一种特殊类型的函数,其特点是其返回值的类型为某一类型的指针。也就是说,这种函数的返回值是一个地址,这个地址指向函数内部某种特定类型的变量或者数据结构。
2.指针函数的定义
指针类型 * (函数名称)(函数的参数列表类型) |
3.指针函数的使用
|
5.2 函数指针
1.函数指针的概念
函数指针是一种特殊类型的指针,它指向函数而非变量。这种指针在内存中储存的是函数的入口地址,我们可以通过这个地址来调用相应的函数。
2.函数指针的定义
函数的返回值类型(*指针名)(函数的参数列表类型) |
3.函数指针的使用
下面是一个函数指针的使用,首先定义一个max函数,然后在主函数内声明函数指针,再将max函数地址传递给函数指针,最后调用函数指针即可。
|