深度理解指针(2)

hello各位小伙伴们,关于指针的了解我们断更了好久了,接下来这几天我会带领大家继续我们指针的学习。

数组名的理解

我们首先来看一段代码:

cpp 复制代码
#include<stdio.h>
int main ()
{
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    printf("arr     =  %p",arr);
    printf("&arr[0] =  %p",&arr[0]);
    printf("&arr    =  %p",&arr); 
    return 0;
}

经过编译器输出后均为00B6FACC,我们会自然而然的认为arr,&arr 0 ,还有&arr都会表示数组首元素地址,但是表示首元素地址的只有arr还有&arr 0 。&arr表示的是整个数组的地址。我们可以通过地址加1来进行验证一下。

cpp 复制代码
#include<stdio.h>
int main ()
{
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    printf("arr      =   %p\n",arr);
    printf("arr + 1  =   %p\n",arr + 1);
    printf("&arr[0]  =   %p\n",&arr[0]);
    printf("&arr[0]+1=   %p\n",&arr[0]+1);
    printf("&arr     =   %p\n",&arr);
    printf("&arr+1   =   %p\n",&arr+1);
}

发现只有arr还有&arr0 在加1后会跳过一整型(4个字节) ,而&arr+1会跳过整个元素。

所以&arr和&arr0、arr不一样,同时指针类型决定加减整数的步长。

使用指针访问一维数组

我通常在访问一维数组的时候会使用下标来进行访问。

cpp 复制代码
#include<stdio.h>
int main ()
{
    int arr[10] = {0};
    int i = 0;
    //进行读取
    for(i = 0;i < 10;i++)
    {
        scanf("%d",arr[i]);
    }
    //进行输出
    for(i = 0;i < 10;i++)
    {
        printf("%d",arr[i]);
    }
    return 0; 
}

在学习了指针后可以使用指针地址来进行访问。

cpp 复制代码
//
    ......替换
//
int *p = arr;
scanf("%d",p + i);
//
    ......替换
//
printf("%d",*(p + i));

我们将arr(数组首元素地址)赋给p(指针变量)后,p和arr等价。所以arr i 与p i 所表达的含义相同。

cpp 复制代码
//
    ......
//
scanf("%d", p + i);
//scanf("%d", arr + i);
//
    ......
//

	//printf("%d", *(p + i));
	// printf("%d", p[i]);
	//printf("%d", *(arr + i));
	//printf("%d", arr[i]);
    printf("%d", i[arr]);

arri和*(arr+i)是完全等价的,同时arri在执行的时候也会转换成*(arr+i)。 只是操作符iarr会转换成*(i+arr)。

一维数组传参的本质

先上代码:

cpp 复制代码
#include<stdio.h>
void test(int arr[])
{
    int sz2 = sizeof(arr)/sizeof(arr[0]);
    printf("sz2 = %d\n",sz2);
}
int main()
{
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    int sz1 = sizeof(arr)/sizeof(arr[0]);
    test(arr);
    printf("sz1 = %d\n",sz1);
} 

输出结果为sz1 = 10,sz2 = 1。为什么呢?

在test(arr)中我们可以看到传递的arr其实是数组首元素地址,在void test进行接收的时候的其实接收的是指针变量而不是真正又重新创建了一个新的数组。所以写成void test(int*p)比较好。但未来更加好理解所以写成int arr 也不会是错的哦。

总结一下:

test(arr);传递数组名arr,是数组首元素的地址。

1、函数形参的部分是不会真实创建数组的,那抹就不需要数组的大小。

2、函数形参部分应该使用指针变量来接收int *p一维数组传参的时候,形参可以写成数组的形式,主要是为了方便使用,形参也可以写成指针变量的形式。

这就是一维数组传参的本质。

二级指针

我们学习了一级指针是用来存储某一个整型变量或者字符变量地址的,是变量就会有地址那么一级指针变量谁来存储呢?答案:使用二级指针来对一级指针的地址进行存储。

cpp 复制代码
#include<stdio.h>
int main ()
{
    int a = 10;
    int *pa = &a;
    int **ppa = &pa;
    return 0;
}

对int*pa和int**ppa的理解:*代表pa的类型是指针类型,int代表*pa所指向的内容(int a = 10)为整型。 int* *ppa第二个*代表ppa的类型为指针类型,int*代表*ppa所指向的内容(int*pa = &a)为指针类型。

如果想要对a进行输出可以使用:

cpp 复制代码
//
    ............
//
    printf("%d",**ppa);
//

*ppa为pa,*pa就为a=10了。

指针数组

整型数组是用来存放整型,字符数组是用来存放字符,同理指针数组是用来存放指针的。

使用指针数组来进行访问:

cpp 复制代码
#include<stdio.h>
int main ()
{
    int a = 10;
    int b = 20;
    int c = 30;
    int*arr[] = {&a,&b,&c};
    int i = 0;
    for(i = 0;i < 3;i++)
    {
        printf("%d",*arr[i]);
    }
}

使用指针数组来模仿二维数组

cpp 复制代码
#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	int* arr[] = { arr1,arr2,arr3 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			//printf("%d ", *(arr[i] + j));
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

OK本期就到这里啦,这期主要讲解了指针与数组的关系,小伙伴们一定要好好学习指针,为后期学习打下坚实的基础。拜拜!(下期讲解深度理解指针3)

相关推荐
汉克老师3 分钟前
GESP7级C++考试语法知识(二、指数函数(3、综合练习)
c++·算法·数学建模·指数函数·gesp7级·复利
C++ 老炮儿的技术栈10 分钟前
Ubuntu root账号自动登陆
linux·运维·服务器·c语言·c++·ubuntu·visual studio
林间码客36 分钟前
04 ROC曲线与AUC:从零开始手动计算
大数据·人工智能·算法
Irissgwe40 分钟前
map/set/multimap/multiset 的底层逻辑与实现
数据结构·c++·算法·二叉树·stl·c·红黑树
IronMurphy44 分钟前
【算法五十八】23. 合并 K 个升序链表
数据结构·算法·链表
思茂信息1 小时前
CST软件基于液态金属开关的方向图可重构天线
服务器·算法·重构·cst·仿真软件·电磁仿真
(Charon)1 小时前
【C++ 面试高频:内存管理、RAII 和智能指针详解】
java·开发语言·word
月疯1 小时前
PPG研究中暑的算法记录
算法
春日见1 小时前
vscode的AI编程插件推荐:
大数据·ide·vscode·算法·机器学习·编辑器·ai编程
轻刀快马1 小时前
跨越软硬件的共鸣(二):从 Cache 写策略看 Redis 与 DB 的一致性博弈
java·开发语言·redis·计算机组成原理