深入理解指针2

数组名是什么?

 这个问题是一个难点,有的人觉得很简单,其实没那么容易!!!

int main()
{
	int a = 10;  //a是栈区的一块变量
	int* pa = &a; //&a 是把a的地址取出来放到变量pa里面
	//...
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//arr一定是数组的变量名字,那么...
	int(*pArr)[10] = &arr; 
	//把数组arr的地址通过&arr取出来,放到了数组指针pArr中
	printf("%d\n", *arr); //1
	//这个通过*arr竟然打印出来1(第一个元素)
	//这儿arr可能是首元素的地址,通过*把内容拿出来了。
	return 0;
}

 这个数组名在不同的情况下有不同的含义,至于为什么一个数组的名字为什么有不同含义,是怎么实现的,我不会,感觉这样搞得东西让人有一点难受!!!

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%zd\n", sizeof(arr));  //40
	printf("%zd\n", sizeof(int[10]));  //40
	return 0;
}

 上面代码我的理解是:sizeof()这个操作符关注的是()里面的类型是什么,通过类型来确定这个元素的大小!sizeof(数组名)里面就是数组的名字,既然是数组的名字,那么就算的是整个数组的大小!!!

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("&arr[0] = %p\n", &arr[0]);
	printf("&arr[0]+1 = %p\n", &arr[0] + 1);

	printf("arr = %p\n", arr);
	printf("arr+1 = %p\n", arr+1);

	printf("&arr = %p\n", &arr);
	printf("&arr+1 = %p\n", &arr+1);
	return 0;
}

1
 通过上面代码可以看出arr和arr+1的差是4个字节,证明了arr就是首元素的地址,并且把首元素的地址打印出来和arr大的一样,进一步证明了arr是首元素的地址。
 &arr和&arr+1相差40个字节,证明了&arr是整个数组的地址。

1
 sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩,单位是字节
• &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素的地址是有区别的)
除此之外,任何地⽅使⽤数组名,数组名都表⽰⾸元素的地址。

使用指针访问数组及其数组传参的本质

指针访问数组

 这个很简单其实arr除了两种特殊情况,它就是首元素的地址,这儿说一下,数组在内存中是连续存储的。

int main()
{
	char str[4] = { 'a','b','c','d' };
	printf("&str[0] = %p\n", &str[0]);
	printf("&str[1] = %p\n", &str[1]);
	printf("&str[2] = %p\n", &str[2]);
	printf("&str[3] = %p\n", &str[3]);
	return 0;
}

1
 既然这样,访问数组的方式多种多样.

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(int);
	int* p = arr;
	for (int i = 0; i < sz; i++) {
		//根据在内存中连续访问
		printf("%d ", *(p + i));
		printf("%d ", *(arr + i));
		//根据下标访问
		printf("%d ", p[i]);
		printf("%d ", arr[i]);
	}
	return 0;
}

 只要搞清楚了它的本质是什么,随便你怎么访问!!!

一维数组传参的本质

 一维数组传参的本质其实就是传首元素的地址!!!证明如下:

void Print(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

void Print(int* arr, int sz)
{
	//...
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(int);
	Print(arr, sz);
	return 0;
}

 虽然形参有时候写成了int arr[],它的本质是一个指针变量,用于接受首元素的地址。

二级指针

 二级指针准确的来说是二级指针变量,是用来接受一级指针变量的地址的,没有什么神奇的!!!

int main()
{
	//创建a
	int a = 10;
	//存a的地址
	int *pa = &a;
	//存pa的地址
	int* *ppa = &pa; //二级指针变量
	return 0;
}

 这儿在解释一下int* *ppa = &pa;这个代码. *ppa说明ppa是指针变量,int * 说明ppa是指向int *的指针变量,也就是说是存int *类型地址的指针变量。
1

指针数组

 指针数组还是数组,只不过里面存放的元素的是指针类型!!!
 用指针数组模拟二维数组!

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	//把3个数组的首元素地址存到指针数组里面
	int* pArr[] = { arr1,arr2,arr3 };
	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			//通过pArr[i]可以把每个数组的首地址拿出来,在索引找元素
			printf("%d ", pArr[i][j]);
		}
		printf("\n");
	}
	printf("\n");
	return 0;
}




 完结!!!

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值