常量指针与指针常量、指针数组与数组指针、指针函数和函数指针

发布时间 2023-03-22 21:10:47作者: MyXjl

易混淆的几个概念

常量指针与指针常量

int value = 0;
int num = 1;
// 1.当const位于 * 左边时,称为常量指针
const int* p1 = &value;
int const *p2 = &value;
*p1 = 10; 					// error 不能改变指针所指变量的值
p1 = #					// right 可以改变指针的指向

// 2.当const位于 * 右边时,称为指针常量
int* const p3 = &value;
*p3 = 10;					// right 可以改变指针所指变量的值
p3 = #					// error 不能改变指针的指向

// 3.双const
const int* const p4 = &value;
/* 指针所指变量的值和指针的指向都不可改变 */

指针数组与数组指针

指针数组:其本质是一个数组,数组中的每个元素都是一个指针。

数组指针:其本质是一个指针,该指针指向一个数组的首地址。

int* Arrar[10];				// 指针数组,Array是一个包含10个指针元素的数组

int (*pArray)[10];			// 数组指针,pArray是一个指向int [10]类型的指针

注意数组指针与数组名称的区别:

#include <iostream>
#include <stdio.h>

using std::cout;
using std::endl;

int main()
{
    char (*pa)[4];
    char a[4];
    char b[3][4] = {0};
    
    //pa = a;           // error
    pa = &a;            // ok
    pa = b;             // ok,二维数组的首地址可以赋值给数组指针

    printf("pa = %p\n",pa);
    printf("pa + 1 = %p\n",pa + 1);
    printf("a = %p\n",a);
    printf("a + 1 = %p\n",a + 1);
    printf("b = %p\n",b);
    printf("b + 1 = %p\n",b + 1);

    return 0;
}


运行结果:

指针数组在参数传递时的使用

指针数组常用在主函数传参,在写主函数时,参数有两个。一个确定参数个数,一个是指针数组用来接收每个参数(字符串)的地址。不能传递整个数组过去,如果数组很大,这样内存利用率很低,所以应该传递数组的首地址,用一个指针接收这个地址。因此,指针数组对应着二级指针

int main(int argc,char* argv[])
{
    //...
}

数组指针传参时的使用

数组指针既然是一个指针,那么就是用来接收地址,在传参时就接收数组的地址,所以数组指针对应着二维数组

void func(int (*p)[4])			//子函数的形参,数组指针
{
    //...
}

int main()
{
    int a[3][4] = {0};			// 主函数定义二维数组
    func(a);					// 主函数调用子函数,传入的实参是二维数组的首地址
}

指针函数和函数指针

函数指针:如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。

例如,线程的创建函数的第三个参数就是函数指针:

int func(int a);		// 函数声明
int (*pfunc) (int a);	// 定义一个函数指针
pfunc = func;			// 将func函数的首地址赋给指针变量pfunc

指针函数:返回值为指针的函数。