• 指针【理论知识速成】(3)


    一.指针的使用和传值调用:

    在了解指针的传址调用前,先来额外了解一下 “传值调用”

    1.传值调用:

    对于来看这个帖子的你相信代码展示胜过千言万语

    #include 
    #include
    int convert(int a, int b)
    {
    	int c= 0;
    	 c = a;
    	 a = b;
    	 b = c;
    	return(a, b);
    }
    int main()
    {
    	int x = 0;
    	int y = 30;
    	convert(x, y);
    	printf("x=%d y=%d", x, y);
    	return 0;
    }
    //输出结果依然为x=0,y=30;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    那为什么通过函数调用最终x,y的结果依然没有被改变?因为在调用时形参a,b也会单独开辟一块新的空间,a与x之间与b同y之间依旧相互独立,所以a是a,x是x,同理b是b,y是y,a只是继承了x的数值而已,b 也只是继承了y的数值而已。所以传值调用的定义就把变量本身传递给了函数
    那如果想通过函数调用改变x,y又该怎么办呢?接下来就需要了解传址调用啦

    2.传址调用:

    同样的定义来之前先将代码呈上

    #include 
    #include
    int convert(int * a, int * b)
    {
    	int c= 0;
    	 c = *a;
    	 *a = *b;
    	 *b = c;
    	return(*a, *b);
    }
    int main()
    {
    	int x = 0;
    	int y = 30;
    	convert(&x, &y);
    	printf("x=%d y=%d", x, y);
    	return 0;
    }
    //输出结果为x=30,y=0;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    此代码不同于上一代码,此码将x,y的地址通过指针传递到函数convert中,成功调换了x,y的值。所以将变量的地址传递给函数,就叫做传址调用
    。#### 3.传值调用传址调用分别在何种情况下使用:
    了解了传值调用与传址调用后那么在何种情况下使用传址调用,又该在何种情况下使用传值调用呢?

    答:在不需要改变变量本身时可采用传值调用,否则采用传址调用。

    二.指针和数组的关系

    前面提到过指针可以用来查询地址,int *p=arr, *p=arr[0],又提到过指针类型的作用,即为指针+1时所跳过的字节数,这一块则是在细致的讲指针如何遍历数组

    1.数组名的理解

    int main()
    {
    	int arr[] = { 1,2,3,4 ,5};
    	printf("%p ", arr);
    	printf("%p ", &arr);
    	printf("%p ", &arr[0]);
    	printf("%p ", sizeof(arr));
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出结果:

    在这里插入图片描述

    由此可看到上述四组输出arr,&arr,&arr[0],都指向了同一地址,是不是证明三种指针完全性等,事实真的是这样嘛,再来看一组代码

    #include
    int main()
    {
    	int arr[] = { 1,2,3,4 ,5};
    	printf("%p ", arr);
    	printf("%p\n", arr+1);
    	printf("%p ", &arr);
    	printf("%p\n", &arr+1);
    	printf("%p ", &arr[0]);
    	printf("%p\n", &arr[0]+1);
    	printf("%p\n ", sizeof(arr));
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    输出结果:
    在这里插入图片描述
    在上述结果中arr与arr[0]在+1后也指向同一地址,而&arr,则指向了其它区域,经过计算发现arr与arr[0]+1跳过的字节长度为一个元素,而&arr+1跳过的长度为一个数组,综上可以确定arr与arr[0]是完全相等的,指向的位置为元素的首地址,但同样有例外**&arr取的就是整个元素的地址,除此之外sizeof(arr)取的也是整个元素的地址**。

    2.使用指针访问数组

    #include
    int main()
    {
    	int arr[10] = {};
    	int* p = arr;
    	int j = 0;
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	for (j = 0; j < sz; j++)
    	{
    		scanf("%d", p + j);
    	}
    	for (j = 0; j < sz; j++)
    	{
    		printf("%d", p + j);//将p+j改为p[j],也完全可以,结果不会产生改变
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3.一维数组传参的本质

    数组在传参的时候所传的是数组首元素的地址

    #include
    int print(int arr[])//传递的其实是一个指针
    {
    	int sz = sizeof(arr) / sizeof(arr[0]);//这里算的是指针的大小比上元素个数的大小
    	printf("s=%d", sz);
    	return 0;
    }
    int main()
    {
    	int arr[10] = {};
    	print(arr);
    	return 0;
    }
    //程序的输出结果在x64的环境下为2,x86为1.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    二.二维指针

    在正式了解二维指针前,可以先联想“二维数组”,二维数组的定义就是以一维数组为元素组成的数组,可推测二维指针大概意思是指向一维指针的指针就叫做二维指针。
    在这里插入图片描述

    1.代码表示:

    int *p=0;//此为一维指针
    int ** pp=0;//此为指向一维数组*p,的二维指针*pp(二维指针的名称不一定和一维指针的名称有关系)
    
    • 1
    • 2

    2.组成:

    在这里插入图片描述
    不要把二维指针想的过于复杂,其实*p也就是一个指针变量

    3.作用:

    二维指针可以通过查询一维指针指向的地址,寻找到变量

    #include
    int main()
    {
    	int a = 0;
    	int* p = &a;
    	int** q = &p;
    	printf("%d", **q);
    	return 0;
    }
    //输出结果为0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    三.指针数组

    同样的在了解指针数组前先联想“整型数组”,没错指针数组就是由指针组成的数组,就是这么好懂
    在这里插入图片描述

    1.表示方式以及组成:

    int arr[]={1,2,3,4};//这个是整型数组,int 表示的就是数组元素的类型是int 
    int * arr[]={arr,arr1,arr2}//这个是指针数组,int *表示的就是数组元素类型是int *
    
    • 1
    • 2

    2.:指针数组模拟二维数组:

    #include
    int main()
    {
    	int arr[] = { 1,2,3 };
    	int arr1[] = { 2,3,4 };
    	int arr2[] = { 3,4,5 };
    	int* a[] = { arr,arr1,arr2 };
    	int i, j;
    	for (i = 0; i < 3; i++)
    	{
    		for (j = 0; j < 3; j++)
    		{
    			printf("%d ", a[i][j]);//也可以写成*(*(a[i])+j)
    		}
    		printf("%d\n");
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    注:二维数组中的每个元素都是连续存放的,而指针数组中的每个元素并不确保是连续存放

  • 相关阅读:
    小节2:Python数学运算
    Pycharm远程连接服务器不能debug问题
    vue-router(路由)详细
    【Java】解决Java报错:ConcurrentModificationException
    春节静态HTML网页作业模板 传统节日文化网站设计作品 静态学生网页设计作业简单网页制作
    jupyter notebook闪退解决,安美解决
    pandas:jupyter notebook笔记(更新中)
    01背包、完全背包进阶理解(全网最详细)
    基于nodejs+vue酒店综合服务[程序+论文+开题]-计算机毕业设计
    深度学习基础与线性回归实例
  • 原文地址:https://blog.csdn.net/hot_water_oh/article/details/136516795