admin管理员组

文章数量:1487745

深入理解并打败C语言难关之一————指针(3)

前言:

昨天把指针最为基础的内容讲完了,并且详细说明了传值调用和传址调用的区别(这次我也是做到了每日一更,感觉有好多想写的但是没有写完),下面不多废话,下面进入本文想要说的内容

正文:

1.数组名的理解

1,1数组名是什么

其实数组名我在之前就解释过了,现在我们正式的来介绍它,数组名是数组首元素的地址,通过代码的撰写就可以看出来二者是一样的,代码以及展示图如下:

代码语言:javascript代码运行次数:0运行复制
#include<stdio.h>
int main()
{
    int arr[10] = {0};
    int *p = &arr[0];
    printf("%p",arr);
    printf("%p",p);
    return 0;
}

  在说上面之前,我想起来我忘记说%p这个占位符的作用了,这个占位符是代表着地址的占位符,想要打印地址就需要它,不难看出,上面两个地址打印出来的结果是一样的,所以可以更好的理解数组名就是数组首元素的地址,不过,这也不是绝对的,下面一种特殊情况数组名就不是数组第一个元素的地址。

1.2数组名的几种特殊情况

  1.2.1sizeof(arr)

我们知道,sizeof运算符是用来计算长度的,上面讲了,arr指的是数组第一个元素的地址,按道理来讲,我们计算arr的长度应该就是第一个元素的长度即四个字节,但是看见下面的代码和打印结果:

代码语言:javascript代码运行次数:0运行复制
#include<stdio.h>
int main()
{
    int arr[10] = {0};
    printf("%zd",sizeof(arr));
    return 0;
}

  我们不难看出,这里打印的结果是40个字节,为什么会打印出40呢?因为这是arr整体的元素个数,所以此时sizeof(arr)并不是第一个元素的长度,而是整个元素的长度,这个一定要记住,在某些企业的笔试题中或者正常的考试题中可能会出一个类似这样的题来迷惑你,所以我们要记住这个特殊情况! 不要出错,不要出错,不要出错!

1.2.2&arr

上面小编说过,arr是数组名,代表着数组第一个元素的地址,那么我们如果直接对arr去地址呢?这种情况我们先通过代码打印看一下:

代码语言:javascript代码运行次数:0运行复制
#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
	printf("%p\n", &arr);
	return 0;
}

  看到这里可能有些读者朋友会想,这三个的地址不都是相同的吗?是不是&arr就是数组第一个元素的地址呢?当然,如果真一样的话,我写这个小标题就一点意义都没有了,先不要着急,我们再看一下下面这个代码就可以知道&arr到底指的是什么了:

代码语言:javascript代码运行次数:0运行复制
#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr + 1);
	printf("%p\n", &arr[1]);
	printf("%p\n", &arr + 1);
	return 0;
}

  这个时候就可以很清楚的发现三者的不同了,前两个肯定是一样的(前面的知识点的运用),而第三个,经过我们的计算,发现比前两个多了36个字节的内存空间 ,这是为什么呢?我也不卖关子了,其实取地址arr取到的是整个数组的地址,所以我们在进行加1操作的时候,其余都是加了一个字节,而&arr是跳跃了一个完全的数组,从而我们在想要取到地址的时候,一定要知晓取到的应该是一个完整的数组地址,不过刚开始指向的是数组第一个元素的地址罢了,在进行加减的时候一定要小心。

小结:

  我们在使用数组名的时候一定要注意这两个特殊情况,除了这两个特殊情况意外,其余的数组名都是代表首元素的地址

2.使用指针去访问数组

2.1指针如何访问数组

其实用指针数组我在上一节课的代码中就已经实现了,以后我还是得改掉超前讲的坏毛病,不多废话,我们知道数组名就是数组第一个元素的地址,所以我们在使用输入函数的时候便可以用数组名来替代&arr[i]类似这样的写法,这样可以减少我们在使用scanf函数的时候忘记运用取地址符的尴尬情况(小编就时常忘记写这个,我还抱怨是编译器的问题,

本文标签: 深入理解并打败C语言难关之一指针(3)