C语言笔记之4种类型的指针

    技术2025-06-08  14

    目录

    什么是指针指向数组元素的指针指向整一个数组的指针指向函数的指针

    1- 什么是指针

    指针是指向另外一个地址的变量,这个指针变量本身也存在一个地址,即一个地址上存储了另外一个变量的地址。

    一个指针:单单纯纯的就是一个变量地址。格式:数据类型* 指针变量名(如:int* p;)指针数组:是指数组类型的指针,数组中,每一个元素都是一个指针。该数组由许多个指针组成。格式:数据类型* 指针数组变量名[数组大小](如:int* arr[10];表示该数组由10个指针组成)

    2- 指向数组元素的指针

    格式:数据类型* 指针变量名(如:int*p;)

    例子

    #include<stdio.h> int main() { //定义一个数组 int arr[]={1,2,3}; //定一个指针 赋值为NULL int* p=NULL; //让指针指向数组首元素 p=arr; printf("从头到尾遍历数组的结果:\n"); //用指针,从头到尾遍历数组 for(int i=0;i<sizeof(arr)/4;i++) { printf("数组元素arr[%d]=%d\n",i,*p); p++; } printf("\n从尾到头遍历数组的结果:\n"); //让指针指向数组尾部元素 p=&arr[sizeof(arr)/4-1]; //用指针,从尾到头遍历数组 for(int i=0;i<sizeof(arr)/4;i++) { printf("数组元素arr[%d]=%d\n",i,*p); p--; } return 0; }

    结果

    从头到尾遍历数组的结果: 数组元素arr[0]=1 数组元素arr[1]=2 数组元素arr[2]=3 从尾到头遍历数组的结果: 数组元素arr[0]=3 数组元素arr[1]=2 数组元素arr[2]=1

    补充:指针数组

    #include <stdio.h> const int MAX = 3; int main () { int var[] = {10, 100, 200}; int i, *ptr[MAX]; for ( i = 0; i < MAX; i++) { ptr[i] = &var[i]; /* 赋值为整数的地址 */ } for ( i = 0; i < MAX; i++) { printf("Value of var[%d] = %d\n", i, *ptr[i] ); } return 0; }

    结果

    Value of var[0] = 10 Value of var[1] = 100 Value of var[2] = 200

    3- 指向整一个数组的数组指针

    格式:(数据类型*)[指向的数组大小];(如:(int*)[10];表示指向一个有10个元素的整一个数组数组。)

    例子

    #include<stdio.h> int main() { //定义一个数组 int arr[]={1,2,3}; //定一个指针 赋值为NULL int(*p)[3]=&arr; //让指针指向数组首元素 p=arr; printf("从头到尾遍历数组的结果:\n"); //用指针,从头到尾遍历数组 for(int i=0;i<sizeof(arr)/4;i++) { printf("数组元素arr[%d]=%d\n",i,(*p)[i]); } return 0; }

    结果

    从头到尾遍历数组的结果: 数组元素arr[0]=1 数组元素arr[1]=2 数组元素arr[2]=3

    引用中文网

    对指针数组和数组指针的概念,相信很多C程序员都会混淆。下面通过两个简单的语句来分析一下二者之间的区别,示例代码如下所示: int p1[5]; int (p2)[5]; 首先,对于语句“intp1[5]”,因为“[]”的优先级要比“”要高,所以 p1 先与“[]”结合,构成一个数组的定义,数组名为 p1,而“int*”修饰的是数组的内容,即数组的每个元素。也就是说,该数组包含 5 个指向 int 类型数据的指针,如图 1 所示,因此,它是一个指针数组。

    其次,对于语句“int(p2)[5]”,“()”的优先级比“[]”高,“”号和 p2 构成一个指针的定义,指针变量名为 p2,而 int 修饰的是数组的内容,即数组的每个元素。也就是说,p2 是一个指针,它指向一个包含 5 个 int 类型数据的数组,如图 2 所示。很显然,它是一个数组指针,数组在这里并没有名字,是个匿名数组。

    由此可见,对指针数组来说,首先它是一个数组,数组的元素都是指针,也就是说该数组存储的是指针,数组占多少个字节由数组本身决定;而对数组指针来说,首先它是一个指针,它指向一个数组,也就是说它是指向数组的指针,在 32 位系统下永远占 4 字节,至于它指向的数组占多少字节,这个不能够确定,要看具体情况。

    了解指针数组和数组指针二者之间的区别之后,继续来看下面的示例代码: int arr[5]={1,2,3,4,5}; int (*p1)[5] = &arr; /下面是错误的/ int (*p2)[5] = arr; 不难看出,在上面的示例代码中,&arr 是指整个数组的首地址,而 arr 是指数组首元素的首地址,虽然所表示的意义不同,但二者之间的值却是相同的。那么问题出来了,既然值是相同的,为什么语句“int(p1)[5]=&arr”是正确的,而语句“int(p2)[5]=arr”却在有些编译器下运行时会提示错误信息呢(如在 Microsoft Visual Studio 2010 中提示的错误信息为“a value of type"int"cannot be used to initialize an entity of type"int()[5]"”)?

    其实原因很简单,在 C 语言中,赋值符号“=”号两边的数据类型必须是相同的,如果不同,则需要显示或隐式类型转换。在这里,p1 和 p2 都是数组指针,指向的是整个数组。p1 这个定义的“=”号两边的数据类型完全一致,而 p2 这个定义的“=”号两边的数据类型就不一致了(左边的类型是指向整个数组的指针,而右边的数据类型是指向单个字符的指针),因此会提示错误信息。

    4- 指向函数的函数指针

    格式:函数返回的数据类型(* 指针变量名)(函数参数1,函数参数2…) 如:int (*p) ( int , int );

    #include<stdio.h> void fun(int n) { printf("n的值为:%d", n); } int main() { //定义一个指向函数的变量 void(*p)(int); //将函数地址赋值给指针 p = &fun; //利用指针调用函数 p(1); //或 (*p)(1); return 0; }

    结果

    输入:1 显示:1 显示:1

    总结

    普通指针(int*p=NULL);指针函数(int*p[5];数组中每一个元素都是普通指针。)数组指针(int(*p)[5];指向整一个数组的指针。)函数指针(int(*p)(int);指向一个函数的指针。)
    Processed: 0.012, SQL: 9