关于指针的基本知识,什么是指针?(小白版)

目录

1.什么是指针?

 2.多级指针

3.常用指针

1.整形指针

2.字符指针

3.数组指针

3.1 &数组名VS数组名

3.2数组指针的使用

3.3数组传参

4.函数指针


1.什么是指针?

       指针全名为指针变量,我们知道计算机在存储数据是有序存放的,而对于如何能够使用到存放的数据,我们就需要一个门牌号来区别每个数据所在的位置,而这个门牌号就是我们常说的地址,指针变量就是用来存放这些地址的变量。

1.指针的大小为固定的4/8个字节(32或64位平台)。

2.指针是有类型的,指针的类型决定了指针加减整数时的步长以及解引用指针是的权限。

4.指针加减整数时,以所指向数据类型的字节为单位进行变动,例:

#include<stdio.h>
int main()
{
	int* p = NULL;
	printf("%p\n", p );   //00000000
	printf("%p\n", p + 1);//00000004
	return 0;
}

 2.多级指针

       正如上一点所说,指针也是变量,因此指针在内存中也是通过地址的形式来存储的,因此一级指针的地址我们用二级指针来表示,例:

#include<stdio.h>
int main()
{
	int* p = NULL;
	int** p1 = &p;
	printf("%p\n", p );   //00000000
	printf("%p\n", p1);//0073FDB0
	return 0;
}

      其中二级指针p1是存储一级指针p地址的指针变量。以此类推,我们还可以有三级指针,四级指针等等。但只需要懂得其核心思想,其他的并不常用。

3.常用指针

1.整形指针

      整形指针是指,指针所指向的数据类型为整形,用int*来定义,如int* p=&a,其中int表示p所指向的数据为整形,*则提示p为指针变量。

2.字符指针

 与整形指针类似,我们知道有一种指针类型为字符指针char*;

int main()
{
	char ch = 'w';
	char* p = &ch;
	*p = 'w';
	return 0;
}

除此之外, 还有一种使用方法:

int main()
{
	char* chr = "hell0";
	printf("%c", *chr);
	return 0;
}

看起来是将一个字符串放到了指针变量chr中,但其实是将首元素h的地址放到了chr中。

3.数组指针

      顾名思义,数组指针就是把一个数组的地址放到一个指针变量中,则这个指针变量就是数组指针。它的本质还是一个指针,这与指针数组有这本质上的区别。(指针数组本质上是一个数组,数组中的元素都是指针)

int* a[10];
int(*b)[10];

     其中,a先与[10]结合,通过数组的定义,我们可以得知a为数组名,这个数组一共有10和元素,每个元素都是int*类型,因此a为指针数组。

      因为有括号的存在,b与*先结合,这就说明b是一个指针,它指向的类型是int [10],是一个数组,其中有10个元素,元素的类型是int,因此b为数组指针。

       在数组指针这块的知识中,常见的难点就是数组名的使用。

3.1 &数组名VS数组名

int arr[10];

我们都知道arr是数组名,数组名表示数组首元素的地址。

请看下面一段代码:

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);   //00D5F81C
	printf("%p\n", &arr);  //00D5F81C
	printf("%p\n", arr+1); //00D5F820
	printf("%p\n", &arr+1);//00D5F844
	return 0;
}

其中arr与&arr的地址相同,但是在加一之后地址就大不相同,这是为什么?

      正如我们之前所提到的,指针的整数运算是按照指向数据的类型进行计算的,从这我们就可以看出arr与&arr看似存储的地址相同,但类型却不相同。这是因为在单独使用数组名时,数组名表示首元素的地址,但是&数组名表示的是整个数组的地址,其中的数组名表示的是整个数组。 

tips:一般情况下,数组名表示首元素地址,但两种情况除外:1.&数组名。2.sizeof(数组名)。这两种情况下,数组名表示整个数组。

3.2数组指针的使用

数组指针指向的是数组,因此其中存放的应该是数组的地址。

int main()
{
	int arr[10] = { 0 };
	int(*p)[10] = &arr;//将arr数组的地址传给指针变量p
	return 0;
}

3.3数组传参

一维数组传参:

void test(int arr[])//ok?
{}
void test(int arr[10])//ok?
{}
void test(int* arr)//ok?
{}
void test2(int* arr[20])//ok?
{}
void test2(int** arr)//ok?
{}
int main()
{
	int arr[10] = {0};
	int* arr2[20] = {0};
	test(arr);
	test2(arr2);
	return 0;
}

上述形参的书写形式都是正确的,

      test(arr)中的实参就是arr数组的首元素地址,在形参的部分我们需要用一个一级指针来接受实参。

      test2(arr2)中的实参为指针数组arr2中首元素的地址,因此我们需要在形参部分采用一个二级指针来接受实参。

tips:在指针变量中,arr[0]等价于*(arr+0),*arr[0]等价于**(arr+0)。

二维数组传参:

void test(int arr[3][5])//ok
{}
void test(int arr[][])//x
{}
void test(int arr[][5])//ok
{}
void test(int *arr)//x
{}
void test(int* arr[5])//x
{}
void test(int (*arr)[5])//ok
{}
void test(int **arr)//x
{}
int main()
{
int arr[3][5] = {0};
test(arr);
}

      在二维数组中,每一个元素都是一个一维数组。test(arr)中的实参是首元素的地址,也就是一个一维数组的地址,因此在形参部分我们可以用一个数组指针来接收实参。

tips:在指针部分,int arr[][5]等价于int (*arr)[5]。

4.函数指针

函数指针:指向函数的指针被称为函数指针。

#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test); //00421249
printf("%p\n", &test);//00421249
return 0;
}

      输出的两个地址完全一样,都是test函数的地址,因为函数名和&函数名都表示函数的地址,这一点与数组名略有差异。

那函数指针该如何保存呢?

void test()
{
printf("hehe\n");
}
void (*pfun1)();
void *pfun2();

    答案是pfun1。 首先,能给存储地址,就要求pfun1或者pfun2是指针,其中只有pfun1是指针,因为*先与pfun1结合,表示其为指针变量,所指向的函数类型是void ();而pfun2表示的是函数名,这个函数返回值为void*类型。

      关于函数指针还有一个难点就是函数指针数组,也就是说把一系列的函数的地址存放在一个数组中,这个数组就是函数指针数组。关于函数指针数组,会在后面的博客中单独梳理知识。

本人拙见,大佬勿怪!^v^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值