int main() { int a[3]={1,10,20}; printf("%u %u %u \n" ,&a,a,&a[0]); return 0; }
这将为所有三个打印相同的值。我知道a和&a[0]是相同的,但&a怎么也是相同的呢?
u5i3ibmn1#
为了获得最大兼容性,应始终使用%p并显式强制转换为void*以使用printf打印指针值。当一个数组的名字在表达式上下文中使用,而不是作为sizeof或一元&的操作数时,它衰减为指向它的第一个元素的指针。这意味着a和&a[0]具有相同的类型(int*)和值。&a是数组本身的地址,因此具有类型int (*)[3]。数组对象从其第一个元素开始,因此数组第一个元素的地址将与数组本身的地址具有相同的值,尽管表达式&a[0]和&a有不同的类型。
%p
void*
printf
sizeof
&
a
&a[0]
int*
&a
int (*)[3]
pdkcd3nj2#
我的C是生疏的,但据我所知,&a是数组开始的地址,它将完全对应于&a[0],因为数组的开始是第一个元素。再说一次,我对C有点生疏,所以我会听从有更好专业知识的人。
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
gz5pxeao4#
&a是“数组的地址”。这是数组在内存中的位置,但它有一个特殊类型“指向数组的指针“。&a[0]是“数组第0个元素的地址”。由于数组中第0个元素之前没有任何内容,因此这是内存中的同一位置,但类型为“指针指向“。a是“数组”。但是在C或C中,你不能真正地通过值传递数组给函数(比如printf)。你只能假装这样做。(在C中,你可以通过引用传递数组,但是C没有通过引用传递。)但是真正发生的是数组“衰减”成指向第一个元素的指针,就像你写了&a[0]一样。发生这种情况是因为(我在这里主要是推测)在C中,它被认为是有用的和可取的:(a)能够修改传入数组的内容;(B)调用函数时不必将整个数组复制到堆栈上。因此C欺骗了你,而是将指向原始数组的指针放到堆栈上。由于语法相同,所以你永远不会真正注意到区别-当你用你认为是数组但实际上是指针的东西编写a[0]时,它访问指针所指向的内存就好像它是一个数组一样(不管它是否真的是--现在已经没有办法判断了)。在C++中,这种行为是为了向后兼容而保留的。
a[0]
dgtucam15#
在C语言中,数组名指向数组的第一个元素。因此,通过声明&a,您将引用第一个元素的内存地址。
zkure5ic6#
这是令人困惑的,因为说(ArrayName是指针)过于简单,实际上编译器不处理数组名这种方式,事实上(Array indexing = Pointer arthimetics)。将此应用到您的代码&a[0]〉〉,可以理解,这是返回数组中第一个元素的地址,不会混淆&a〉〉根据我们对指针的理解,我们期望它能打印出任意一个存储数组第一个元素地址的存储单元,当然它必须是唯一的!?实际上这个假设是不正确的,因为编译器处理&a的方式和处理a的方式是一样的,编译器会生成汇编代码来完成同样的任务,返回同样的位置,这是数组和指针的核心区别之一。同样,&a = a也很有意义,因为a本质上是一个常量指针,指向一个固定地址,没有理由让另一个指针指向它,而不是直接指向常量指针(a)所指向的东西,在本例中是数组中的第一个元素。此外,这里还有一个“陷阱”。&a[0]〉〉发出以下类型的指针pointer to integer&a和a〉〉发出一个如下类型的指针pointer to array of integers所以,它们都指向相同的位置,但是它们有不同的C类型!
Array indexing = Pointer arthimetics
pointer to integer
pointer to array of integers
6条答案
按热度按时间u5i3ibmn1#
为了获得最大兼容性,应始终使用
%p
并显式强制转换为void*
以使用printf
打印指针值。当一个数组的名字在表达式上下文中使用,而不是作为
sizeof
或一元&
的操作数时,它衰减为指向它的第一个元素的指针。这意味着
a
和&a[0]
具有相同的类型(int*
)和值。&a
是数组本身的地址,因此具有类型int (*)[3]
。数组对象从其第一个元素开始,因此数组第一个元素的地址将与数组本身的地址具有相同的值,尽管表达式&a[0]
和&a
有不同的类型。pdkcd3nj2#
我的C是生疏的,但据我所知,&a是数组开始的地址,它将完全对应于&a[0],因为数组的开始是第一个元素。
再说一次,我对C有点生疏,所以我会听从有更好专业知识的人。
cyej8jka3#
在这种情况下,& a恰好与a相同,这是因为a的大小是静态的,如果你用a指针指向一个数组,那么它将是一个不同的数字,而其他两个指针给你的结果是相同的。
例如:
输出示例如下:
2849911432二849911408
gz5pxeao4#
&a
是“数组的地址”。这是数组在内存中的位置,但它有一个特殊类型“指向数组的指针“。&a[0]
是“数组第0个元素的地址”。由于数组中第0个元素之前没有任何内容,因此这是内存中的同一位置,但类型为“指针指向“。a
是“数组”。但是在C或C中,你不能真正地通过值传递数组给函数(比如printf
)。你只能假装这样做。(在C中,你可以通过引用传递数组,但是C没有通过引用传递。)但是真正发生的是数组“衰减”成指向第一个元素的指针,就像你写了&a[0]
一样。发生这种情况是因为(我在这里主要是推测)在C中,它被认为是有用的和可取的:(a)能够修改传入数组的内容;(B)调用函数时不必将整个数组复制到堆栈上。因此C欺骗了你,而是将指向原始数组的指针放到堆栈上。由于语法相同,所以你永远不会真正注意到区别-当你用你认为是数组但实际上是指针的东西编写
a[0]
时,它访问指针所指向的内存就好像它是一个数组一样(不管它是否真的是--现在已经没有办法判断了)。在C++中,这种行为是为了向后兼容而保留的。dgtucam15#
在C语言中,数组名指向数组的第一个元素。
因此,通过声明
&a
,您将引用第一个元素的内存地址。zkure5ic6#
这是令人困惑的,因为说(ArrayName是指针)过于简单,实际上编译器不处理数组名这种方式,事实上(
Array indexing = Pointer arthimetics
)。将此应用到您的代码
&a[0]
〉〉,可以理解,这是返回数组中第一个元素的地址,不会混淆&a
〉〉根据我们对指针的理解,我们期望它能打印出任意一个存储数组第一个元素地址的存储单元,当然它必须是唯一的!?实际上这个假设是不正确的,因为编译器处理
&a
的方式和处理a
的方式是一样的,编译器会生成汇编代码来完成同样的任务,返回同样的位置,这是数组和指针的核心区别之一。同样,
&a
=a
也很有意义,因为a
本质上是一个常量指针,指向一个固定地址,没有理由让另一个指针指向它,而不是直接指向常量指针(a
)所指向的东西,在本例中是数组中的第一个元素。此外,这里还有一个“陷阱”。
&a[0]
〉〉发出以下类型的指针pointer to integer
&a
和a
〉〉发出一个如下类型的指针pointer to array of integers
所以,它们都指向相同的位置,但是它们有不同的C类型!