鱼C论坛

 找回密码
 立即注册
查看: 2153|回复: 9

[已解决]数组地址和数组首元素地址问题

[复制链接]
发表于 2020-4-11 23:50:48 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
大佬们,对于数组,我一直理解的是 数组本身的地址和首元素地址是不一样的,比如        若 int a[10]
&a表示数组本身的地址,而 a 表示数组首元素的地址,即 a[0] 的地址,两个地址是不一样的。
可是我今天用代码试了一下,在主函数中主函数中 &a ,a,&a[0] 表示的地址一样,而在其他函数中却不一样。这让我搞的有点懵。
还有就是函数实参只要吧数组的首地址传过去就可以了吗,我用&a,a,a[0] 都能传过去,在函数中都能使用这个数组。
希望大佬们可以解答一下疑惑,十分感谢!
最佳答案
2020-4-12 00:34:53
在定义数组的函数(不一定是主函数)中,数组名可以把自身当做指针,数组名即数组的首地址,数字首元素的地址也是数组首地址,当然取数组本身地址也是一样的。
虽然这三者的地址是一样的。但是含义不一样。尤其是数组名和数组名取地址。数组名取地址实际上是一个数组指针,数组名是一个指针,两者的区别在+1时能看出来,数组名取地址 +1跳过的是整个数组的长度,数组名+1跳过的是一个元素的长度。
#include<stdio.h>
#include<math.h>
void fun(int a[])
{
    printf("a    :%p\n",a);
    printf("&a   :%p\n",&a);
    printf("&a[0]:%p\n",&a[0]);
 
}
int main()
{
    int a[5]={1,2,3,4,5};
    printf("a    :%p\n",a);
    printf("a+1  :%p\n",a+1);
    printf("&a+1 :%p\n",&a+1);
    printf("&a[0]:%p\n",&a[0]+1);
    fun(a);
    return 0;
}

然而当数组以参数的形式传进函数时,实际上它就是一个新的指针了,只是该指针指向了那个数组的首地址,
由于数组与指针的特殊性,仍然可以以数组的形式使用其对应的元素,但是该指针有自己的空间,也有自己的地址。
看一下下图,这是我之前做的一张图,刚好能表达这个意思
在定义数组的函数内,&temp、temp和&temp[0]都是该数组的首地址;
在调用数组的函数内,&p[0]和p都是数组的首地址,但是&p就是指针的地址了。
啊啊.jpg

将数组作为参数传递时,只要把数组首地址传过去就可以了。这句话是对的。
但是你写的有一点是不对的,传该地址只能是数组名或者数组首元素的地址,即  a  或者 &a[0] , 不能传&a  更不能传 a[0]
1.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-4-12 00:20:34 | 显示全部楼层
首先声明:你的理解完全正确,但是如下:

void show(int array[])//传的是指针,但是这个array是这个函数的局部变量,不同于主函数的array,而是一个新的变量,虽然传指针,但是传的是数组元素的指针,不是数组整体(也就是主函数array)的
{
        printf("array: %p+++\n", array);
        printf("==========\n");
        printf("array: %p\n", array);
        printf("&array:%p\n", &array);
        printf("&array[0] :%p\n", &array[0]);
        printf("&array[4] :%p\n", &array[4]);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-12 00:27:32 | 显示全部楼层
本帖最后由 howzyao 于 2020-4-12 00:29 编辑

int a[10];
&a;
a[0] == 一个int,同时是首个元素
a没有实际int意义,只有关联int的意义,a就是一个指针,指向int [0]~[9]这组数组的意思,我把它叫做数组头,a指一组 被连续占用的 内存的 一个标签.
cout<< a<< " "<<&a<<endl; //一定是一样的.

另外,当指针入实参时,地址发生变化,是由于函数机制造成的:
当array[]入参时,系统把array的实际地址中的值,也就是所有的0~9的这些内存中的一串值,一并复制到一个新的地址,且在当前函数作用域有效,当函数结束时,
这些临时复制过来的所有值,都将被释放,而array[]这个实参,所指向的这片连续内存中的值,是原封不动地不受破坏.
实际上array[]或写成*array 也值得一试,
这样效果也应当是一样,*号,就是解除引用操作符,它解除指针array所指向的内存地址, 而引用这个地址中的值,我是这么理解它的意思的,供大家指正.

0~9这10个下标的10个元素,可以看作独立的int它们分别处于不同的内层中,由于是数组,所以,两个相邻int的内存地址,是有意义的存在,
需要我们自己去想,这是学习C++内存管理的一种常识性基础,看多了,就可以看出一些规律来.这不会太难明白.

这下明白了一切没有?可以的话,赏个分?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-12 00:34:53 | 显示全部楼层    本楼为最佳答案   
在定义数组的函数(不一定是主函数)中,数组名可以把自身当做指针,数组名即数组的首地址,数字首元素的地址也是数组首地址,当然取数组本身地址也是一样的。
虽然这三者的地址是一样的。但是含义不一样。尤其是数组名和数组名取地址。数组名取地址实际上是一个数组指针,数组名是一个指针,两者的区别在+1时能看出来,数组名取地址 +1跳过的是整个数组的长度,数组名+1跳过的是一个元素的长度。
#include<stdio.h>
#include<math.h>
void fun(int a[])
{
    printf("a    :%p\n",a);
    printf("&a   :%p\n",&a);
    printf("&a[0]:%p\n",&a[0]);
 
}
int main()
{
    int a[5]={1,2,3,4,5};
    printf("a    :%p\n",a);
    printf("a+1  :%p\n",a+1);
    printf("&a+1 :%p\n",&a+1);
    printf("&a[0]:%p\n",&a[0]+1);
    fun(a);
    return 0;
}

然而当数组以参数的形式传进函数时,实际上它就是一个新的指针了,只是该指针指向了那个数组的首地址,
由于数组与指针的特殊性,仍然可以以数组的形式使用其对应的元素,但是该指针有自己的空间,也有自己的地址。
看一下下图,这是我之前做的一张图,刚好能表达这个意思
在定义数组的函数内,&temp、temp和&temp[0]都是该数组的首地址;
在调用数组的函数内,&p[0]和p都是数组的首地址,但是&p就是指针的地址了。
啊啊.jpg

将数组作为参数传递时,只要把数组首地址传过去就可以了。这句话是对的。
但是你写的有一点是不对的,传该地址只能是数组名或者数组首元素的地址,即  a  或者 &a[0] , 不能传&a  更不能传 a[0]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-12 00:41:26 | 显示全部楼层
howzyao 发表于 2020-4-12 00:27
int a[10];
&a;
a[0] == 一个int,同时是首个元素
当array[]入参时,系统把array的实际地址中的值,也就是所有的0~9的这些内存中的一串值,一并复制到一个新的地址,且在当前函数作用域有效,当函数结束时,
这些临时复制过来的所有值,都将被释放,而array[]这个实参,所指向的这片连续内存中的值,是原封不动地不受破坏.

这句话是不对的。数组作为参数传递时,传递的是地址,不是传递原数组的值,在函数中修改数组内容也就是修改原数组的内容。,并不是你所说的不会破坏原数组。
你所说的是一般变量的值传递,歘递过来的是一个原值的复制,函数结束释放掉,不会影响原值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-12 01:45:55 From FishC Mobile | 显示全部楼层
楼上说的非常全面,全部读透肯定能理解这个知识点。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-12 01:52:30 From FishC Mobile | 显示全部楼层
sunrise085 发表于 2020-4-12 00:34
在定义数组的函数(不一定是主函数)中,数组名可以把自身当做指针,数组名即数组的首地址,数字首元素的地 ...

其实数组传地址时可以传&a,不用数组指针而是普通指针接收即可。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-12 10:33:05 | 显示全部楼层
sunrise085 发表于 2020-4-12 00:34
在定义数组的函数(不一定是主函数)中,数组名可以把自身当做指针,数组名即数组的首地址,数字首元素的地 ...

好的,谢谢,我理解了大部分,解释的非常仔细。
但是我用了&a,也能吧数组传过去。
还有就是我在调用的函数中修改数组元素,到主函数中值也改变了。
实参传递过去的数组的首地址吧,相当于传递的指针过去,不是把原来的数组内容复制一份,以值传递的形式传过去的吧。
希望大佬在给我解答一下疑惑!
非常感谢!
#include <stdio.h>

void show(int array[])
{
    int i;
    printf("show函数中改变前:\n");
    for(i=0;i<5;i++)
    {
        printf("%d  ",*(array+i));
    }
    printf("\n\n");
    printf("改变  array[2]  的值:");
    scanf("%d",&array[2]);
    printf("show函数中改变后:\n");
    for(i=0;i<5;i++)
    {
        printf("%d  ",*(array+i));
    }
    printf("\n\n");
}
int main()
{
    int a[5]={1,1,1,1,1};
    int i;
    printf("主函数中,改变前:\n");
    for(i=0;i<5;i++)
    {
        printf("%d  ",*(a+i));
    }
    printf("\n\n");
    show(&a);
    printf("主函数中,改变后:\n");
    for(i=0;i<5;i++)
    {
        printf("%d  ",*(a+i));
    }
    printf("\n\n");

    return;
}[img]as[/img]
2.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-12 23:59:41 From FishC Mobile | 显示全部楼层
终于看到杨左使麾下坛主李坛主了,感谢sunrise纠正,传入&a确实比较好,10长度整个40字节全部传入,以供编辑,好。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-13 00:03:11 From FishC Mobile | 显示全部楼层
依据入参数组的用途,如果只读,就想要避免不经意的破坏,对传入数组来说,就要被保护起来,请使用限定常量const int &做为函数原型吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-15 06:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表