目录
  • 前言
  • 指针运算
    • 指针±整数
    • 指针-指针
    • 指针的关系运算
  • 指针和数组
    • 二级指针
      • 指针数组
        • 举例 1
        • 举例 2
      • 总结

        前言

        本文接着上一篇内容,继续学习指针相关知识点。

        指针运算

        • 指针±整数
        • 指针-指针
        • 指针的关系运算

        指针±整数

        #define VALUE 5
        int main()
        {
        	float values[VALUE];
        	float *vp;
        	//指针+-指针,关系运算
        	for (vp = &values[0]; vp < &values[VALUE];)
        	{
        		*vp++ = 0;//通过这样完成初始化
        	}
        	for (int i = 0; i < VALUE; i++)
        	{
        		printf("%d ", values[i]);
        	}
        	return 0;
        }
        

        C语言指针超详细讲解下篇

        指针-指针

        int main()
        {
        	int arr[10] = { 0 };
        	printf("%d\n", &arr[9] - &arr[0]);//得到元素的个数
        	printf("%d\n", sizeof(arr)/sizeof(arr[0]));//计算元素个数
        	int* p0 = &arr[0];
        	int* p9 = &arr[9];
        	printf("%d\n", (p9 - p0));//得到元素的个数
        	return 0;
        }
        

        通过数组首尾元素的地址相减,得出的就是数组元素的个数,

        -int*表示指针指向的地址里面,存放的数据类型是整形,占用4个字节

        • 数组元素地址+1,就是寻找下一个元素的地址,就会移动4个字节

        C语言指针超详细讲解下篇

        通过调试更加清楚的观察到这一现象,int 数组每个元素占用四个字节:

        • &arr[0]: 0x005cf7f8
        • &arr[0]+1: 0x005cf7fc,地址移动1位,即int*指针移动1位,字节增加4个。

        C语言指针超详细讲解下篇

        前提条件:两个指针必须指向同一块空间:

        char ch[5];
        int arr[6];
        %arr[4]-&ch[3];//错误的
        

        前面的文章介绍了字符串长度的方法两种方法:

        • 循环
        • 递归

        这里介绍第三种方法, 指针

        int mylen(char* pa)//传参是数组首元素的地址
        {
        	char* p = pa;//首元素地址
        	while (*pa)//元素不是‘0'
        	{
        		pa++;//通过地址访问字符串
        	}
        	//结尾字符0的地址减首元素地址
        	return pa - p;//指针相减是元素的个数
        }
        int main()
        {
        	char arr[] = "abcdef";
        	int len = mylen(arr);
        	printf("%d", len);
        	return 0;
        }
        

        指针的关系运算

        标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与

        指向第一个元素之前的那个内存位置的指针进行比较

        int main()
        {
        	//
        	for (vp = &values[5]; vp > &values[0];)
        	{
        		*--vp = 0;
        	}
        	for (vp = &values[5-1]; vp >= &values[0];vp--)//不允许
        	//地址会指向首元素前面的地址,这是不允许的
        	{
        		*vp = 0;
        	}
        	return 0;
        }
        

        指针和数组

        int main()
        {
        	int arr[10] = {1,2,3,4,5,6,7,8,9,0};
        	printf("%p\n", arr);
        	printf("%p\n", &arr[0]);
        	int *p = arr;//p存放的是数组首元素的地址
        	return 0;
        }
        

        数组名和数组首元素的地址是一样的。数组名表示的是数组首元素的地址。(2种情况除外,数组系列文章详细介绍了)

        C语言指针超详细讲解下篇

        既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问一个就成为可能

        int main()
        {
        	int arr[] = {1,2,3,4,5,6,7,8,9,0};
        	int *p = arr; //指针存放数组首元素的地址
        	int sz = sizeof(arr)/sizeof(arr[0]);
        	for(int i=0; i<sz; i++)
        	{
        		printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p+i);
        	}
        	return 0;
        }
        

        C语言指针超详细讲解下篇

        观察上图,所以 p+i 其实计算的是数组 arr 下标为 i 元素的地址。那就可以直接通过指针来访问数组:

        int main()
        {
        	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
        	int* p = arr;
        	int sz = sizeof(arr) / sizeof(arr[0]);
        	for (int i = 0; i < sz; i++)
        	{
        		printf("%d ",*(p + i));
        	}
        	printf("\n");
        	for (int i = 0; i < sz; i++)
        	{
        		printf("%d ", *(p++));
        	}
        	printf("\n");
        	for (int i = 0; i < sz; i++)
        	{
        		printf("%d ", arr[i]);
        	}
        	return 0;
        }
        

        C语言指针超详细讲解下篇

        二级指针

        指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?这就是 二级指针

        int main()
        {
        	int a = 10;
        	int* pa = &a;
        	int** ppa = &pa;
        	return 0;
        }
        
        • a的地址存放在指针pa中,pa是一级指针
        • pa的地址存放在ppa中,ppa是二级指针

        C语言指针超详细讲解下篇

        对于二级指针的运算有:

        *ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa .

        int b = 20;
        *ppa = &b;//等价于 pa = &b;
        

        **ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a

        **ppa = 30;
        //等价于*pa = 30;
        //等价于a = 30;
        

        指针数组

        指针数组是指针还是数组?

        是数组。是存放指针的数组

        在数组系列文章中,已经介绍了整形数组,字符数组:

        int arr1[5];//占用20个字节
        char arr2[5];//占用5个字节
        

        C语言指针超详细讲解下篇

        举例 1

        指针数组:

        int main()
        {
        	int data1[] = { 1,2,3,4,5 };
        	int data2[] = { 2,3,4,5,6 };
        	int data3[] = { 3,4,5,6,7 };
        	//看成二维数组
        	int* arr[3] = { data1,data2,data3 };
        	for (int i = 0; i < 3; i++)
        	{
        		for (int j = 0; j < 5; j++)
        		{//[]是操作符
        			printf("%d ", arr[i][j]);//不需要解引用
        		}
        		printf("\n");
        	}
        	   
        	return 0;
        }
        

        arr3是一个数组,有五个元素,每个元素是一个整形指针,就是一个地址:

        • arr[0],为元素data1,是指针变量,本身也是一维数组 { 1,2,3,4,5 } 的数组名,代表首元素地址
        • arr[1],为元素data2,是指针变量,本身也是一维数组 { 2,3,4,5,6 } 的数组名,代表首元素地址
        • arr[2],为元素data3,是指针变量,本身也是一维数组 { 3,4,5,6,7 } 的数组名,代表首元素地址

        C语言指针超详细讲解下篇

        C语言指针超详细讲解下篇

        通过调试也能发现:

        • 指针数组首元素data,是指针变量,也是一维数组首元素的地址
        • 通过数组名 + i 就能访问数组里的元素
        • 指针数组可看成二维数组
        arr[0]=data1;//指针数组首元素data,是指针变量,也是一维数组首元素的地址
        arr[0][0]=data1[0];//看成一维数组
        arr[0][1]=data1[1];
        arr[0][2]=data1[2];
        arr[0][3]=data1[3];
        arr[0][4]=data1[4];
        

        C语言指针超详细讲解下篇

        打印结果见下图:

        C语言指针超详细讲解下篇

        代码换成下面这个效果一样,从地址的解引用角度去写:

        int main()
        {
        	int data1[] = { 1,2,3,4,5 };
        	int data2[] = { 2,3,4,5,6 };
        	int data3[] = { 3,4,5,6,7 };
        	//看成二维数组
        	int* arr[3] = { data1,data2,data3 };
        	for (int i = 0; i < 3; i++)
        	{
        		for (int j = 0; j < 5; j++)
        		{
        			printf("%d ", *(arr[i]+j));//地址访问解引用
        		}
        		printf("\n");
        	}   
        	return 0;
        }
        
        

        C语言指针超详细讲解下篇

        举例 2

        指针数组中元素都是指针变量,就是地址

        int main()
        {
        	int a = 10;
        	int b = 11;
        	int c = 12;
        	int d = 13;
        	int e = 14;
        	int* arr[5] = { &a,&b,&c,&d,&e };//指针数组存放的元素是指针变量,就是地址
        	for (int  i = 0; i < 5; i++)
        	{
        		printf("%d ", *(arr[i]));//地址解引用
        	}
        	return 0;
        }
        

        C语言指针超详细讲解下篇

        总结

        本文继续学习了指针相关的知识点,指针是C语言的重中之重,在基础阶段,指针的学习就告一段落了。

        下一篇将学习结构体的知识点。(链接直达)

        声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。