C语言 数组静态声明中第一个元素的地址

yqlxgs2m  于 2023-03-07  发布在  其他
关注(0)|答案(6)|浏览(143)
int main()
{
    int a[3]={1,10,20};
    printf("%u %u %u \n" ,&a,a,&a[0]);
    return 0;
}

这将为所有三个打印相同的值。我知道a和&a[0]是相同的,但&a怎么也是相同的呢?

u5i3ibmn

u5i3ibmn1#

为了获得最大兼容性,应始终使用%p并显式强制转换为void*以使用printf打印指针值。
当一个数组的名字在表达式上下文中使用,而不是作为sizeof或一元&的操作数时,它衰减为指向它的第一个元素的指针。
这意味着a&a[0]具有相同的类型(int*)和值。&a是数组本身的地址,因此具有类型int (*)[3]。数组对象从其第一个元素开始,因此数组第一个元素的地址将与数组本身的地址具有相同的值,尽管表达式&a[0]&a有不同的类型。

pdkcd3nj

pdkcd3nj2#

我的C是生疏的,但据我所知,&a是数组开始的地址,它将完全对应于&a[0],因为数组的开始是第一个元素。
再说一次,我对C有点生疏,所以我会听从有更好专业知识的人。

cyej8jka

cyej8jka3#

在这种情况下,& a恰好与a相同,这是因为a的大小是静态的,如果你用a指针指向一个数组,那么它将是一个不同的数字,而其他两个指针给你的结果是相同的。
例如:

int main()
{
    int b[3]={1,10,20};
    int* a = b;
    printf("%u %u %u \n" ,&a,a,&a[0]);
    return 0;
}

输出示例如下:
2849911432二849911408

gz5pxeao

gz5pxeao4#

&a是“数组的地址”。这是数组在内存中的位置,但它有一个特殊类型“指向数组的指针“。
&a[0]是“数组第0个元素的地址”。由于数组中第0个元素之前没有任何内容,因此这是内存中的同一位置,但类型为“指针指向“。
a是“数组”。但是在C或C中,你不能真正地通过值传递数组给函数(比如printf)。你只能假装这样做。(在C中,你可以通过引用传递数组,但是C没有通过引用传递。)但是真正发生的是数组“衰减”成指向第一个元素的指针,就像你写了&a[0]一样。
发生这种情况是因为(我在这里主要是推测)在C中,它被认为是有用的和可取的:(a)能够修改传入数组的内容;(B)调用函数时不必将整个数组复制到堆栈上。因此C欺骗了你,而是将指向原始数组的指针放到堆栈上。由于语法相同,所以你永远不会真正注意到区别-当你用你认为是数组但实际上是指针的东西编写a[0]时,它访问指针所指向的内存就好像它是一个数组一样(不管它是否真的是--现在已经没有办法判断了)。在C++中,这种行为是为了向后兼容而保留的。

dgtucam1

dgtucam15#

在C语言中,数组名指向数组的第一个元素。
因此,通过声明&a,您将引用第一个元素的内存地址。

zkure5ic

zkure5ic6#

这是令人困惑的,因为说(ArrayName是指针)过于简单,实际上编译器不处理数组名这种方式,事实上(Array indexing = Pointer arthimetics)。
将此应用到您的代码&a[0]〉〉,可以理解,这是返回数组中第一个元素的地址,不会混淆
&a〉〉根据我们对指针的理解,我们期望它能打印出任意一个存储数组第一个元素地址的存储单元,当然它必须是唯一的!?
实际上这个假设是不正确的,因为编译器处理&a的方式和处理a的方式是一样的,编译器会生成汇编代码来完成同样的任务,返回同样的位置,这是数组和指针的核心区别之一。
同样,&a = a也很有意义,因为a本质上是一个常量指针,指向一个固定地址,没有理由让另一个指针指向它,而不是直接指向常量指针(a)所指向的东西,在本例中是数组中的第一个元素。
此外,这里还有一个“陷阱”。
&a[0]〉〉发出以下类型的指针pointer to integer
&aa〉〉发出一个如下类型的指针pointer to array of integers所以,它们都指向相同的位置,但是它们有不同的C类型!

相关问题