C语言学习过程总结(16)——指针(4)

一、数组名的理解

我们直接使用%p打印出地址来看看&arr【0】 和 arr的不同:

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

}

很容易看出来两者的输出结果相同,用指针的话来说就是两个指向同一个地方。

数组名和数组首元素的地址打印结果一样,所以数组名就是数组的第一个元素的地址

    printf("%d\n", sizeof(arr));
那上面这个代码的打印结果是什么呢?

——40

但是我们刚刚知道数组名表示的数组的首元素地址,打印的结果不应该是4或者8吗?

是刚刚的结论错了吗?

当然不是,只不过是有两个例外:

*sizeof(数组名)

在sizeof中单独的放一个数组名,这个数组名就表示整个数组,计算的也就是整个数组的大小 4*10就是40了,单位是字节。

*&数组名

这里的数组名也是表示整个数组,取出的是整个数组的地址。

注意:整个数组的地址和数组首元素地址是有区别的!

举个简单例子:&arr + 1 就是跳过一整个数组;arr + 1 则是跳过数组中的一个元素。

用下面的代码直观感受一下吧

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;
}

(在十六进制中 c 就是12)    (48 ~ 70在十六进制中就是3*16+2=40)

通过运行代码我们可以看到,这⾥我们发现&arr[0]和&arr[0]+1相差4个字节,arr和arr+1 相差4个字节,是因为&arr[0] 和 arr 都是⾸元素的地址,+1就是跳过⼀个元素。但是&arr 和 &arr+1相差40个字节,这就是因为&arr是数组的地址,+1 操作是跳过整个数组的。

数组名是数组⾸元素的地址,但是有2个例外(sizeof(数组名)和 &数组名)

二、用指针访问数组

还是用一组代码来讲解

int main() {
	int arr[10] = { 0 };
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = arr;
	for (i = 0; i < sz; i++) {
		scanf("%d", p + i);
	}

	for (i = 0; i < sz; i++) {
		printf("%-2d", *(p + i));
	}
	return 0;
}

 

因为数组名arr是数组首元素的地址,将其赋值给指针p,这样p就等价与arr,p也指向了数组首元素的地址,这时候使用*(p + i)和p[i]都是可以访问数组的

因为*(p + i)是等价于 p[i]

数组传参的本质

我们在上一节知道了,传参是有传值和传址两种方式的

就可以通过将求数组元素个数的步骤放在函数中来实现

代码如下:

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;
}

sz1和sz2的值并不一样!

如果是传数值的话,两个sz计算出来的结果应该是一样的,结果不一样说明传的是地址,在函数test中的arr是一个存放地址的指针,所以sizeof(arr)计算的是一个地址的字符大小,这样的结果当然是不一样的。

我们可以在定义函数形参的时候就用指针定义

将int arr【】 换成 int * arr更为直观,可以减少出错!

一维数组传参,形参部分可以写成数组的形式也可以写成指针形式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值