C语言笔记(一)

上课时老师提到了一个经典的问题,即把一个二维数组名直接赋值给一个二级指针会引发的问题:

课内问题

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main()
{
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int **q;
q = a; //此处会报错
...
return 0;
}

实际原因是因为二级指针p与二维数组名a并不是同一种数据类型,C语言中并没有多维数组的概念,而是以“数组的数组”方式来实现多维数组。对于二维数组a,是将数组作为数组元素进行储存。

接着老师提问,如何将二维数组赋值给二级指针

于是想到了如下两种方法:

  1. 声明一个指针数组:
1
2
int *temp[3] = {a[0],a[1],a[2]};//依次获取二维数组的“每一行”
p = temp;
  1. 采用malloc函数进行内存分配:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
p = (int** )malloc(3 * sizeof(int*));//初始化二级指针 
if (p == NULL)
{
printf("fail to malloc!");//注意判断未成功分配内存的情况
exit(1);
}
for(int i = 0;i<3;i++)
{
*(p + i) = (int*)malloc(4 * sizeof(int));//为每一个一级指针分配内存
if (*(p + i) == NULL)
{
printf("fail to malloc!");//同上
exit(1);
}
*(p + i) = a[i];//依次赋值
}
...
for(int i = 0;i < 3;i++)
{
free(*(p + i));//注意释放内存以免数据泄露,先依次释放每个一级指针
}
free(p);//释放二级指针

拓展

在上述第二种方法中,可以看出对二级指针指向的每一个一级指针都可以比较自由分配内存,在此自然而然地想到自定义一个函数进行间接分配内存,由此想到了使用函数和二级指针为字符串数组间接分配内存:

定义函数MyMalloc:

形参必须使用二级指针
这里由于是对指针进行操作(这里是操作指针,而非是操作指针指向的值),如果直接用一级指针,那么就相当于是按值传递,传进函数的是该指针的副本,那么可以想象的到,这里需要按地址传递,即采用指针的指针(类似的,如果要对二级指针进行操作,传入函数的形参需定义为三级指针)。(来自于学习链表时的更新💮)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//用于间接分配内存
int MyMalloc(char **ptr,int size)
{
char* temp = NULL;
if(ptr == NULL)//判断二级指针ptr是否成功指向pStr
{
return 1;
}
temp = (char*)malloc(size * sizeof(char));//申请内存
if(temp == NULL)
{
return 1;
}
*ptr = temp;//由于ptr指向pStr,所以此式等价于pStr = temp,即成功指向分配的内存
}

使用函数MyMalloc:

1
2
3
4
5
6
7
int main()
{
char *pStr = NULL;
int buffer = 20;
MyMalloc(&pStr,buffer);//注意实参是"&pStr",让形参ptr指向pStr
...
}

若使用一级指针作为形参,会导致无法正确分配内存。

总结

  • 二级指针需要使用malloc函数初始化分配内存以便使用。
  • 不能想当然,有疑惑就敲出来看看,善用监视功能。
  • 参考文章CSDN

C语言笔记(一)
https://zongjy.github.io/2022/02/28/f72f08471262/
作者
zongjy
发布于
2022年2月28日
许可协议