「C/C++ 01」指针 和 二维数组的创建

本文详细解释了变量和指针的概念,讨论了它们在内存中的作用,以及如何通过指针操作数据。重点讲解了编译器对指针等级的检查,静态和动态二维数组的创建方法,以及使用calloc/free和new/delete进行内存管理。
摘要由CSDN通过智能技术生成

目录

一、变量,变量名和指针  

1. 什么是变量?

2. 变量名和指针

3. 使用指针获取数据 

4. 指针的加减

a. 存放指针的变量的加减

b. 存放指针的变量的自增自减

c.  两个指针相减

二、指针变量和数组变量 

三、编译器对指针的等级有着严格的检查 

四、如何创建一个静态的二维数组?

五、二维数组的动态开辟和释放

1. 使用calloc/free开辟和释放二维数组

2. C++中使用new/delete开辟和释放二维数组


一、变量,变量名和指针  

1. 什么是变量?

        变量就是一个用来存储数据的容器,是内存中的一小块空间,变量的类型向编译器指出了变量可存储的数据的性质,编译器将为变量预留必要的空间。

2. 变量名和指针

        变量名对应一个内存地址,且通过变量名可以直接访问内存空间中的数据。在C/C++中编译器或运行时环境知道变量名对应一个内存地址(指针),并自动通过这个地址来访问或修改内存空间中数据,而不需要我们手动解引用。


        指针就是内存地址的别名,所以指针/地址/内存地址是同一个东西的不同说法,指针变量里存放的就是指针。

        可能为了方便,很多人把指针变量简称为指针,所以现在甚至很多书籍中都把指针变量简称为指针。这也就导致了指针现在有两种含义:地址和存放地址的变量。这样的说法实在是太容易让人混淆,所以为了更好区分,博主在文章中都是把指针和指针变量的概念分开:指针就是地址,指针变量才是存放地址的变量。


        如果把内存空间比作一个酒店房间指针就是这个房间的门牌,可以通过指针找到这个空间,但不能通过指针直接进入这个空间。而变量名就相当于这个房间的门卡,既可以通过变量名直接找到这个空间,也可以直接通过变量名进入这个空间,获取其中的内容。


我们可以通过&(取地址符)后跟变量名来取出一个变量名对应的地址。

3. 使用指针获取数据 

我们通过指针找到的是存放数据的房间,而不是真正的数据,这个时候我们需要使用一把钥匙—— *(解引用符),来进入这个存放数据的空间中取出数据。

4. 指针的加减

a. 存放指针的变量的加减

存放指针的变量能加也能减,但不管加减都要小心越界。

上面的写法等价于:

b. 存放指针的变量的自增自减

  • 存放指针的变量有两种: 数组变量、指针变量。
  • 数组变量不能自增和自减,因为C语言规定它必须存放指向数组起始地址的指针,不能修改,但自增和自减会修改变量的值,所以数组变量不能自增和自减。
  • 指针变量可以自增和自减,和 +1 / -1 没有区别。

c.  两个指针相减

 两个指针不可以相加,但可以相减,相减结果为在数组中的下标之差。

	int a[] = { 1, 2, 3, 4, 5 };
	cout << &a[3] - &a[0] << endl; 

二、指针变量和数组变量 

指针变量和数组变量之间的关系:

        两者本质上是同一种东西,两个变量里存放都是一个指针(地址)。指针变量可以使用[ ]来访问后面的空间中的内容,数组变量也可以使用指针加法来找到后面的空间。[ ] 相当于 指针加法后再解引用。


但无法使用一维指针来创建数组:


所以说一级指针变量就对应着一维数组变量,因为可以通过指针加法找到后面的空间。

三、编译器对指针的等级有着严格的检查 

vs编译器对指针的等级有着严格的检查:即一级指针变量不能存放二级指针。


反之也一样:即二级指针变量也不能存放一级指针。


所以要开辟二维数组,我们要使用二级指针变量来接收指向其起始位置的二级指针。

四、如何创建一个静态的二维数组?

        如果要开辟一个真正意义上的二维数组,则需要使用二级指针变量来接收 一级指针变量的地址 / 一级指针数组的起始地址。


0. 依照之前的理论,可以用二级指针变量接收一级指针变量的地址,强行当成一个二维数组使用:先让一级指针变量指向一个整型,然后让二级指针变量指向一级指针变量的地址。但这样做非常危险,因为按上面的方法创建二维数组我们只申请了一个a[0][0]的空间,在访问a[0][0]以外的空间时都是在越界访问,这些空间如a[0][1]等,很有可能被系统分配给了其他变量,一旦我们想给如a[0][1]等空间赋值时,会引起越界错误。


1. 合理的做法是:在二级指针变量里放一个 一级指针数组的起始地址,数组中的一级指针都指向整型数组。


2. 当然也可以直接把上面的一维指针变量b当作二维数组变量来使用,效果是一样的:


3. 转换成二维数组变量的形式:


        所以要创建静态二维数组,我们首先要创建一个二级指针或一级指针数组,然后让二级指针/一级指针数组中存放的一级指针指向基本类型数组,这样就完成了一个静态二维数组的创建。


五、二维数组的动态开辟和释放

1. 使用calloc/free开辟和释放二维数组

        让一个二级指针变量存放动态开辟的一级指针数组的起始地址,然后让这些一级指针指向动态开辟的基本类型的数组:

// 开辟一个大小为3的一级指针动态数组
int** brr = (int**)calloc(sizeof(int*), 3);
// 让数组中的一级指针动态指向动态开辟的整型数组
brr[0] = (int*)calloc(sizeof(int), 3);
brr[1] = (int*)calloc(sizeof(int), 5);
brr[2] = NULL;
// 赋值
brr[0][0] = 1;
brr[0][1] = 2;
brr[0][2] = 3;
brr[1][0] = 11;
brr[1][1] = 12;
brr[1][2] = 13;
brr[1][3] = 14;
brr[1][4] = 15;
cout << brr[0][2] << endl;
cout << brr[1][4] << endl;
brr[1][4] = 26;
cout << brr[1][4] << endl;

for (int i = 0; i < 3; i++)
	free( brr[i]);
free(brr);


开辟一个n行m列的二维数组:

int main()
{
    int n = 3, m = 4;
	// 先开一个大小为n的指针数组
	int** arr = (int**)malloc(sizeof(int*) * n);

	//对每个一维数组开辟空间
	for (int i = 0; i < n; i++)
		arr[i] = (int*)malloc(sizeof(int) * m);

	//释放
	for (int i = 0; i < n; i++)
		free(arr[i]);
	free(arr);
	return 0;
}

2. C++中使用new/delete开辟和释放二维数组

        一样的步骤:让一个二级指针变量存放动态开辟的一级指针数组的起始地址,然后让这些一级指针指向动态开辟的基本类型的数组:

// 开辟一个大小为3的一级指针动态数组
int** arr = new int* [3]; 
arr[0] = new int[] {1, 2, 3}; // 让数组中的一级指针动态指向动态开辟的整型数组
arr[1] = new int[] {11, 12, 13, 14, 15 };
arr[2] = nullptr; //一定将未初始化的一级指针数组设为空指针,不然释放时会抛异常
cout << arr[0][2] << endl;
cout << arr[1][4] << endl;
arr[1][4] = 26;
cout << arr[1][4] << endl;

for (int i = 0; i < 3; i++)
	delete[] arr[i];
delete[] arr;


开辟一个n行m列的二维数组:

//开辟一个n行m列的二维数组
int n = 3, m = 4;
int** a = new int* [n];// 先开一个大小为n的指针数组
for (int i = 0; i < n; i++)
	a[i] = new int[m];// 再将每个指针指向一个动态数组

cout << a[0][0] << endl; //局部变量不会初始化为0

for (int i = 0; i < n; i++)
	delete[] a[i];
delete[] a;

------------------------END-------------------------

才疏学浅,谬误难免,欢迎各位批评指正。

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烛火萤辉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值