首页 > 其他分享 >深入理解指针2:数组名理解、一维数组传参本质、二级指针、指针数组和数组指针

深入理解指针2:数组名理解、一维数组传参本质、二级指针、指针数组和数组指针

时间:2024-04-04 23:30:50浏览次数:20  
标签:arr int printf 数组名 数组 zippo 指针

1、数组名理解

首先来看一段代码:

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

输出的结果是:40,如果arr是数组首元素的地址,那输出应该是4/8才对。

其实数组名就是数组首元素(第一个元素)的地址是对的,但是有两个例外:

  • sizeof(数组名)。sizeof中单独放数组名,这里的数组表示整个数组,计算的是整个数组的大小,单位是字节
  • &数组名。这里的数组名表示整个数组,取出的是整个数组的地址(不是首元素的地址)。

除此之外,任何地方使用数组名,数组名都表示首元素的地址。

再来看一段代码:

#include <stdio.h>
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;
}

输出结果:

这里我们发现&arr[0]和&arr[0]+1相差4个字节,arr和arr+1相差4个字节,是因为&arr[0]和 arr 都是首元素的地址,+1就是跳过1个元素。

但是&arr 和 &arr + 1 相差40个字节,这就是因为&arr是数组的地址,+1 操作是跳过整个数组的。

2、一维数组传参本质

先看一段代码:

#include <stdio.h>
void test(int arr[])
{
	int sz2 = sizeof(arr) / sizeof(arr[0]);
	printf("sz2 = %d\n", sz2);
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz1 = sizeof(arr) / sizeof(arr[0]);
	printf("sz1 = %d\n", sz1);
	test(arr);
	return 0;
}

输出结果

在数组传参的时候,传递的是数组名,也就是说本质上数组传参本质上传递的是数组首元素的地址。所以函数形参的部分理论上应该使用指针变量来接受首元素的地址。

3、二级指针

假设有下面的声明:

int zippo[4][2];//内含int数组的数组
  • 因为zippo是数组首元素的地址,所以zippo的值和&zippo[0]相同。而zippo[0]本身是一个内含两个整数的数组,所以zippo[0]的值和它首元素(一个整数)的地址(即&zippo[0][0]的值相同。简而言之,zippo[0]是一个占用一个int大小对象的地址。所以zippo和zippo[0]的值相同。
  • 给指针或地址加1,其值会增加对应类型大小的值。在这方面,zippo和zippo[0]不同,因为zippo指向的对象占用了两个int大小,而zippo[0]指向的对象只占用一个int大小。因此,zippo+1和zippo[0]+1的值不同。
  • zippo[0]是该数组首元素(zippo[0][0])的地址,所以 *(zippo[0])表示存储在zippo[0][0]上的值。与此类似,*zippo代表该数组首元素(zippo[0])的值,但是zippo[0]本身是一个int类型值的地址。该值的地址是&zippo[0][0]。所以*zippo就是&zippo[0][0]。**zippo与*&zippo[0][0]等价。

#include <stdio.h>
int main()
{
	int zippo[4][2] = { {2,4},{6,8},{1,3},{5,7} };

	printf("   zippo = %p,      zippo + 1 = %p\n", zippo, zippo + 1);
	printf("zippo[0] = %p,   zippo[0] + 1 = %p\n", zippo[0], zippo[0] + 1);
	printf("  *zippo = %p,     *zippo + 1 = %p\n", *zippo, *zippo + 1);
	printf("zippo[0][0] = %d\n", zippo[0][0]);
	printf("  *zippo[0] = %d\n", *zippo[0]);
	printf("    **zippo = %d\n", **zippo);
	printf("zippo[2][1] = %d\n", zippo[2][1]);
	printf("*(*(zippo+2) + 1) = %d\n", *(*(zippo + 2) + 1));

	return 0;
}

运行结果:

zippo 二维数组首元素的地址(每个元素都是内含两个 int 类型元素的一维数组)

zippo+2  二维数组的第 3个元素 (即一维数组)的地址

*(zippo+2) 二维数组的第 3个元素(即一维数组)的首元素(一个 int 类型的值)地址

*(zippo+2) + 1  二维数组的第 3个元素(即一维数组)的第 2个元素(也是一个 int 类型的值)地址

*(*(zippo+2) + 1)  二维数组的第 3个一维数组元素的第 2个int 类型元素的值,即数组的第3行第2
列的值 (zippo[2][1])

4、指针数组和数组指针

指针数组的本质其实是数组,它里面存放的是指针,数组中每个元素的类型是指针类型(int*或char*)。

指针数组的创建方式:

int * arr[10] = {0};

数组指针的本质其实是指针变量,存放的是数组的地址,能够指向数组的指针变量。

数组指针的创建方式:

int (*pt)[10];

 数组指针的初始化:

int arr[10] = {0};
int (*pt)[10] = &arr;

字符指针变量:

char* p = "hello";

这里本质上是把字符串“hello”,首字符h的地址存放在p中。

标签:arr,int,printf,数组名,数组,zippo,指针
From: https://blog.csdn.net/2303_80078385/article/details/137305371

相关文章

  • 『VUE』11. 操作数组的方法(详细图文注释)
    目录vue中操作数组的方法会修改原数组的会进行渲染更新不修改原数组的不会进行渲染更新push自动渲染concat赋值渲染总结欢迎关注『VUE』专栏,持续更新中欢迎关注『VUE』专栏,持续更新中vue中操作数组的方法vue中数组数据呈现在网页,只检测一开始用到的数......
  • 双指针做题总结2(76. 最小覆盖子串)
    76.最小覆盖子串 思路:双指针滑动窗口问题,指针的移动条件是双指针的核心。 反思:1、考虑右指针已经移动到最右端,无法继续移动的情况。(flag1的思路)2、用map.empty()是要千万注意:map[key]相当于往map中添加元素 代码:classSolution{public:unordered_map<char,i......
  • 数组Api归纳篇——splice与slice
    1、splicesplice() 方法就地移除或者替换已存在的元素/添加新的元素。 语法:splice(start,deleteCount,item)        1、start开始索引    2、deleteCount删除几个    3、item替换/添加的元素    4、返回值:一个包含了【删除的元......
  • c语言中关于字符数组赋值问题
    一维数组代码#include<iostream>#include<cstring>#include<algorithm>usingnamespacestd;constintN=1010;charstr[N];charst[N];chars1[N];chars2[N];/*abcdeabcdeabcdeabcde*/intmain(){ scanf("%s",&str+1); ......
  • 数组赋值
    1publicclassShuZhu{2publicstaticvoidmain(String[]args){3int[]a1={2,3,4,5,6,7,8};4int[]a2=a1;56for(inta3:a17){8System.out.println(a3);9}10System.o......
  • luoguP1102-双指针
    题目链接:P1102A-B数对-洛谷|计算机科学教育新生态(luogu.com.cn)利用单调性求解双指针解法:排序构造出区间单调,则若存在目标值B,B在序列中一定为连续区间,此时通过双指针l和r,此时维护一段区间:有S[L]大于S[I]-C,S[R]大于等于S[I]-C,此时我们枚举每一位,若存在A......
  • 代码随想录DAY1 | 二分,双指针移除元素
    代码随想录DAY1|二分,双指针移除元素题目描述给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。示例1:输入:nums=[-1,0,3,5,9,12],target=9输出:4解释:9出现在nums中并且......
  • 代码随想录算法训练营第一天 | 数组 704.二分查找 27.移除元素
    leetcode704.二分查找题目704.二分查找给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。解题思路代码实现本题对自己的难点有大概的解题思路,但是代码实现有几个点写不出来1、怎么取......
  • 计算给定整数数组中,第i个元素表示从第i个位置开始按摩到最后一个位置能够获得的最大收
    算法:计算给定整数数组中,第i个元素表示从第i个位置开始按摩到最后一个位置能够获得的最大收益。解题思路:使用动态规划方法解决。代码示例:publicintmassage(Vector<Integer>nums){intn=nums.size();if(n<0){return0;}......
  • 4.7 数组的读取和写入,type指令和一些杂项
    4.7数组的读取和写入,type指令和一些杂项可以通过wordptr将db转为dw,然后按照dw的方式去存储数据1.段名也可以把其地址赋给变量assumecs:codesg,ds:data,ss:stackdatasegmentdb12,34dw12,34db'helloworld'dataendsstacksegmentdb10d......