栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言深度理解数组与指针——你真的会用数组吗?

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言深度理解数组与指针——你真的会用数组吗?

1.介绍

本篇是对字符指针、数组指针、指针数组这篇博客进行的补充。

字符指针、数组指针、指针数组以及指针传参——C语言

上一篇博客对字符串常量的介绍较为笼统与模糊,以及对“二维数组”根本没有介绍。

本篇将重点整理数组与指针的关系以及一些便于记忆的代码。

2.字符串常量

我们先研究一段代码:

#include 
int main()
{
	char* str = "abcd";
	char arr[] = "abcd";

	if (str == arr)
		printf("1n");
	else
		printf("0n");
	return 0;
}

输出结果:

这段代码我们介绍过,但是并没有给出很明确的解释。


现在我们来详细分析:

我们用 if else 语句来判断 str 和 arr 的地址是否相同,输出结果为 0 ,即不相同。

我们的问题在于,都使用看起来相同的字符串,为什么地址会不相同。

首先看 char* str = "abcd" ; 这条语句:

 我们再看 char arr[] = "abcd" ; 这条语句:

 3.数组与指针

事实上,在C语言中,只存在一维数组。不是有二维数组吗?这个问题在后面解释。

我们先来看一段代码:

#include 
int main()
{
	char arr1[5] = "abcd";
	char arr2[5] = "abcd";

	//都是把第二个元素改为'B
	arr1[1] = 'B';
	*(arr2 + 1) = 'B';

	printf("%sn", arr1);
	printf("%sn", arr2);
	return 0;
}

输出结果:

 这个例子很好的将 指针 和 数组 联系起来。

实际上,我们对数组的操作只有两种:

一是确定数组的大小。

二是获得首元素的地址。

这就很奇怪了,我们明明使用数组的下标改掉数组的内容了啊!

其实,除了对数组操作的两种方法外,我们想要操作数组,只能使用指针,就算看起来使用的是数组下标,实际上它也是一种指针操作。只不过数组下标是指针操作的简写,被常用而已。

我们再来研究下面这串代码:

#include 
int main()
{
	char str[5] = "abcd";
	char* ps = str;
	printf("%pn",str);
	printf("%pn",ps);
	printf("%pn", &str[0]);
	return 0;
}

运行结果:

可以看见打印出的地址一摸一样。

由此我们得出结论:对于数组来说,在本该出现指针的地方,使用了数组名,那么数组名就被当作首元素地址。

现在我们可以来谈谈 “二维数组” 了。

我们来考虑这段代码:

#include 
int main()
{
	int arr[10][20];
	return 0;
}

我们来试着理解 int arr[10][20]; 是什么意思:

 

 现在理解了 “二维数组” ,现在有一个问题:所有情况下数组名都是首元素地址吗?

我们来看一段代码:

#include 
int main()
{
	int arr[2][3] = { 1,2,3,2,3,4 };
	printf("%dn", sizeof(arr));
	return 0;
}

我们使用操作符 sizeof 计算数组的大小,可见 arr 并不是一个地址。

所以这里有一个特例:如果数组名不是用在sizeof下,那么数组名就是首元素地址。

我们理解了二维数组,那我们想办法来操作它。

我们有 int arr[2][3] = {1,2,3,2,3,4}; ,那我们想输出第二个3,应该如何做?

#include 
int main()
{
	int arr[2][3] = { 1,2,3,2,3,4 };
	printf("%dn", *(*(arr + 1) + 1));
	printf("%dn", arr[1][1]);
	return 0;
}

现在就能输出第二个3了。

由此也可见,当我们使用数组下标,在一定程度上可以简化代码。

4.数组与函数参数

我们来看我们经常使用但是又经常忽略的一种函数传参方式。

#include 
int main()
{
	char str[] = "abcd";
	printf("%sn", str);
	printf("%sn", &str[0]);
	return 0;
}

我们要记得,我们把数组名 str 传给了 printf 函数,也就是把数组的首元素地址给了 printf 函数。

%s 它会自己顺着这个地址往后找,直到找到 '' 。

所以屏幕上会出现:

 

因为我们数组名作为参数传参被转化成数组首元素地址,所以,数组作为函数参数是毫无意义的。 

我们来谈谈二维数组的传参:

#include 

void print2(int (*arr)[3])
{
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d ", *(*(arr+i)+j));
		}
		printf("n");
	}
}
void print1(int arr[2][3])
{
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("n");
	}
}
int main()
{
	int arr[2][3] = { 1,2,3,2,3,4 };
	print1(arr);
	printf("n");
	print2(arr);
	return 0;
}

输出结果:

可以看到 print1 和 print2 的效果一样。实际上 print1 和 print2 毫无差别,上面说过数组作为函数参数是毫无意义的,所以,print1的参数会自动转换为指针。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/965531.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号