二级**指针和指针数组

多级指针与指针数组

指针的指针

指针记录着目标数据对象的首地址和类型。

那么能不能有一个指针它记录一个指针的首地址和类型呢?

我们对一个指针再次取地址,如果能取到 &指针 的地址 那么就会有指针指向一个指针

#include <stdio.h>
int main()
{
    int n = 123;
    int *pn = &n;
    printf("pn = %u\n", pn);
    printf("&pn = %u\n", &pn);//对指针 再次进行取地址
    return 0;
}

我们对整型n变量取地址,获取到一个 int * 类型的指针。将指针存储到指针变量pn中。
之后,我们再对pn取地址。  这就获得了一个存放指针数据的指针

指针的指针是什么类型

 int n = 123;
 int *pn = &n;

  类型 pnn = &pn

那么对存放指针的指针 用什么类型表示呢

int ** 就是 存放指针的指针 的类型

int **p; // 正确
int**p; // 正确
int* *p; // 正确
int * *p; // 正确
int * * p; // 正确

对于空格 没有要求

多级指针

int ** 是一个 int * 类型数据对象的指针,所以被称之为二级指针。

#include <stdio.h>
int main()
{
    int n = 123;
    int *pn = &n;
    int **pnn = &pn;
    printf("**pnn = %d\n", **pnn);
    return 0;
}

取地址过程:

对n使用取地址运算符,获得n的指针pn,类型为 int * 。

对pn使用取地址运算符,获得pn的指针pnn,类型为 int ** 。

取值过程:

对pnn使用取值运算符,将 int ** 还原为 int * 。

对*pnn使用取值运算符,将 int * 还原为 int 。即,还原为n

那么 既然存在 存放指针的指针 那能不能 在对二级指针进行再次的取地址

#include <stdio.h>
int main()
{
    int n = 123; // int
    int *oneStar = &n; // int *
    int **twoStar = &oneStar; // int **
    int ***threeStar = &twoStar; // int ***
    int ****fourStar = &threeStar; // int ****
    int *****fiveStar = &fourStar; // int *****
    printf("n = %d\n", *****fiveStar); // 五次取值,还原为int
    return 0;
}

指针数组

从普通的数组 存放元素为 int 类型的数据

int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5] = {11, 22, 33, 44, 55};
int arr3[5] = {111, 222, 333, 444, 555}

那么可不可以 弄一个数组 里面放着都是指针

[指针 ,指针 ,指针…] 这就是指针数组

int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5] = {11, 22, 33, 44, 55};
int arr3[5] = {111, 222, 333, 444, 555}
//创建 一个指针数组
int * arr[3];  //类型 就是 int * [3]  和int [3]  区别在于一个用于放指针  一个放整数

arr[0]=arr1;
arr[1]=arr2;
arr[2]=arr3;
//arr[ arr1,arr2,arr3]  //数组名存放的是指向首元素的指针
//arr[ arr1首指针,arr2首指针,arr3首指针]

Arr的类型为 int *[3] ,是一个数组。

它有3个元素,每个元素的类型为 int * 。

由于元素类型为指针,所有它也被称为指针数组

int arr1[5] = {1, 2, 3, 4, 5};
int arr2[5] = {11, 22, 33, 44, 55};
int arr3[5] = {111, 222, 333, 444, 555}
//创建 一个指针数组
int * arr[3];  //类型 就是 int * [3]  和int [3]  区别在于一个用于放指针  一个放整数

arr[0]=arr1;
arr[1]=arr2;
arr[2]=arr3;
//arr[ arr1,arr2,arr3]  //数组名存放的是指向首元素的指针
//arr[ arr1首指针,arr2首指针,arr3首指针]
for(int i = 0 ; i < 3; i ++)
{
    //arr 是一个指针  **p 就是存放指针的指针 这个指针存放arr的第一个元素
	int **p = arr + i;
for(int j = 0; j < 5; j++)
{
    //(*p + j)  *p  把**int 转为*int 获得arr[0]的指针 
    //arr1+1 就是arr1的第二个元素
    //*(*p + j)   (*p + j)是地址(某一个数组的下标)   *(*p + j) 对地址取值*(*p + j)
	printf("%d ", *(*p + j));
}
	printf("\n");
}


p ,指向 pToArr 的第一个元素,类型为 int ** 。

*p ,指向 arr1 的第一个元素,类型为 int * 。

*p + j ,指向 arr1 中的第j个元素,类型为 int * 。

*(*p + j) ,为 arr1 中的第j个元素。

函数的返回值

#include <stdio.h>
int* func()
{
    int n = 100;
    return &n;
}
int main()
{
    int* p = func();
    printf("%d\n", *p);
    return 0;
}

这个程序看似正确,并且可以通过编译。但是,却存在潜在问题。
这是因为函数结束后,函数内部的变量也会被回收。所以,变量 n 已经失效了。再去访问它有可能正
常,也有可能得到一些无意义的值或者引发错误。
这样设计的原因是因为函数与函数之间的变量是独立的,即使是同一个函数多次运行,这些变量也是独
立的。在函数返回后,函数内的变量没有继续存在的意义了。所以,函数内的变量将被回收,回收后的
内存空间将给接下来运行的函数使用。
如果你不想让变量被回收,那么可以在变量前加上关键词 static
int* func()
{
static int n = 100; // 关键词static让变量n不被回收
n++; // 变量n自增
return &n;
}
#include <stdio.h>
int main()
{
int* p = func();
printf("%d\n", *p);
func();
printf("%d\n", *p);
func();
printf("%d\n", *p);
func();
printf("%d\n", *p);
func();
printf("%d\n", *p);
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值