指针练习题 -- 涉及一维二维数组等价转换、sizeof与strlen的计算

目录

一、知识点回顾

1. 一维数组传参

2. 二维数组传参

3. sizeof操作符以及strlen字符串计算 

二、案例实操

1. 二维数组中的sizeof计算

  2. printf输出值是多少?-- 两个一维数组


一、知识点回顾

也可以先做题,碰到不会的案例再返回来看看对应的知识点~

1. 一维数组传参

传参的关键:参数的含义,参数的类型

#include<stdio.h>
void print_a(int arr[],int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);//也可以*(arr + i)
	}
}
void print_b(int *arr, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *(arr + i));//也可以arr[i]
        // *(arr + i),arr是数组首元素的地址,arr+i表示数组第i个元素的地址
	}
}
int main()
{
	int arr[6] = { 1,2,3,4,5,6 };
	print_a(arr, 6);
	printf("\n");
	print_b(arr, 6);
	return 0;
}

    print_a(arr, 6) 中传的arr,有两种理解:
①arr本是个一维数组。传一维数组,用一维数组接收。形参用int arr[]
②arr又表示数组首元素的地址。传地址,用指针接收,类型是int* (表示指向int类型)

    *(arr + i) == arr[i] == *(i+arr) == i[arr]   

2. 二维数组传参

 传参的关键:参数的含义,参数的类型

 解引用关键:区别首行的地址&首元素的地址

#include<stdio.h>
void print_a(int arr[2][3])//二维数组传参,必须写列数
{
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d ", arr[i][j]);
		}
	}
}
void print_b(int(*arr)[3], int row, int clo)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < clo; j++)
		{
			printf("%d ", *(*(arr + i) + j));
			//== printf("%d ", *(arr[i] + j));
			//== printf("%d ", (*(arr + i))[j]);
			//== printf("%d ", arr[i][j]);
		}
	}
}
int main()
{
	int arr[2][3] = { 1,2,3,4,5,6 };
	print_a(arr);//二维数组传参,用二维数组接收
	printf("\n");
	print_b(arr,2,3);//二维数组传参,用指针接收
	return 0;
}

   传参传的是二维数组首行(可以看成是一个一维数组)地址&arr,其类型是int(*arr)[3]:
   !!!&arr的类型怎么看
   arr是二维数组首行的地址。地址用指针接收,且指针指向一个数组,所以是一个数组指针

   解读 *(*(arr + i) + j) :  arr+i表示二维数组第i行的地址;*(arr+i)相当于*(&arr),表示第i行的数组名,第i行的数组名又可以看成是一个一维数组首元素的地址;*(*(arr + i) + j)就是第i行第j个元素的值。

   *(*(arr + i) + j) ==  *(arr[i] + j) == (*(arr + i) )[j] == arr[i][j]

3. sizeof操作符以及strlen字符串计算 

详细可以看sizeof操作符与strlen库函数的用法与比较

二、案例实操

1. 二维数组中的sizeof计算

int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a[0][0]));
	printf("%d \n", sizeof(a[0]));
	printf("%d\n", sizeof(a[0] + 1));
	printf("%d\n", sizeof(*(a[0] + 1)));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(*(a + 1)));
	printf("%d\n", sizeof(&a[0] + 1));
	printf("%d\n", sizeof(*(&a[0] + 1)));
	printf("%d\n", sizeof(*a));
	printf("%d \n", sizeof(a[3]));
	return 0;
}

详解:

#include<stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));           //4*4*3=48
	//二维数组的数组名a,单独放在sizeof内部,求的是整个二维数组的大小
	printf("%d\n", sizeof(a[0][0]));     //4
	//a[0][0]表示二维数组第0行第0列这个元素的值,求值的类型的大小--int类型,4个字节
	printf("%d\n", sizeof(a[0]));        //16
	//a[0]表示二维数组第一行的数组名,数组名单独放在sizeof内部,求这一整行(看成一个一维数组)数组的大小。
	printf("%d\n", sizeof(a[0] + 1));    //4/8
	//a[0]+1,a[0]数组名没有单独放在sizeof内部,表示二维数组首行首元素的地址。+1,表示首行第二个元素的地址
	printf("%d\n", sizeof(*(a[0] + 1))); //4
	//*(a[0] + 1))表示首行第二个元素的地址,再解引用,表示首行第二个元素的值。
	printf("%d\n", sizeof(a + 1));       //4/8
	//a二维数组数组名,没有单独放,表示二维数组首行的地址。+1表示第二行的地址
	printf("%d\n", sizeof(*(a + 1)));    //16
	//解引用第二行的地址,拿到第二行数组的数组名。相当于sizeof(a[1]),数组名单独放在sizeof内部。
	printf("%d\n", sizeof(&a[0] + 1));   //4/8
	//a[0]--二维数组首行的数组名,没有单独放,&a[0]表示首行的地址。+1表示第二行的地址
	printf("%d\n", sizeof(*(&a[0] + 1)));//16
	//解引用第二行的地址,拿到第二行的数组名。相当于sizeof(arr[1]),数组名单独放在sizeof内部,求整个数组的大小
	printf("%d\n", sizeof(*a));          //16
	//a--二维数组数组名,没有单独放表示数组首行的地址,*a--拿到二维数组首行数组名。数组名单独放...
	printf("%d\n", sizeof(a[3]));        //16
	//假设有第四行的数组,此时第四行数组的大小是4*4=16
	//sizeof操作符()内部的表达式不参与真实运算,实际上没有去越界访问,只是直到表达式的类型而已
	return 0;
}

 注意事项:

① 区别二维数组中的 a,a[0],*a,&a[0]
a   --   二维数组的数组名
         单独放在sizeof内部表示求整个二维数组的大小;                                                                       没有单独放在sizeof内部表示二维数组首行的地址
a[0] -- 二维数组首行的数组名
         单独放在sizeof内部表示求首行(可看作一维数组)整个数组的大小;                                       没有单独放在siezof内部表示二维数组首行首元素的地址
&a[0] -- 首行的地址即首行整个数组的地址
*a  -- *(二维数组首行的地址),拿到二维数组首行的数组名

!!!首行地址≠首行首元素地址                                                                                              !!!二维数组的首行是一个一维数组                                                                                                  按照二维数组里的一维数组来理解的话:a-二维数组数组名,a[0]-一维数组数组名

② 区别二维数组中的 a+1,a[0]+1,&a[0]+1
a+1         二维数组首行的地址+1->二维数组第二行的地址
a[0]+1     二维数组首行首元素的地址+1->二维数组首行第二个元素的地址
&a[0]+1   &数组名得到二维数组首行的地址,+1->二维数组第二行的地址

  2. printf输出值是多少?-- 两个一维数组

#include<stdio.h>
int main()
{
	int a[12] = { 1,2,3,4,5,6,7,8,9,10,11,12 }, * p[4], i;
	for (i = 0; i < 4; i++)
	{
		p[i] = &a[i * 3];
	}
	printf("%d\n",p[3][2]); 
	return 0;
}

 分析p是一个指针数组, p[3][2]==*(p[3]+2)。p+3是指针数组第四个元素地址&a[9] -> *(a[9]+2)==*(a[11])==12

画个图便于理解:

 a[9]一维数组a的第10个元素的值,&a[9]拿到第10个元素的地址,&a[9]+2拿到第12个元素的地址&a[11],再解引用*(&a[11]),最后得到a[11]。a[11]是数组a的第12个元素的值。

 结果:12

 关键:① 理解二维数组中的等价转换  ②*&a[11]==a[11]

~ 后续继续更新...

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值