求问一个关于数组和指针的问题

2019-10-16 10:15:36 +08:00
 waiaan
void main(void)
{
  int a[5] = {1, 2, 3, 4, 5};
  printf("%p\n", a);
  printf("%p\n", &a);
}

为什么打印出来结果会是一样的?

谢谢。

3893 次点击
所在节点    C
19 条回复
stebest
2019-10-16 10:23:15 +08:00
第一个是数组第一个元素的指针,第二个是数组的指针,打印出来的结果当然一样
kljsandjb
2019-10-16 10:27:19 +08:00
c 语言的 legacy
Rasphino
2019-10-16 10:30:26 +08:00
int *p;

int (*p)[5];
waiaan
2019-10-16 10:32:04 +08:00
@stebest
所以 a 还不算一个变量?
dawn009
2019-10-16 10:49:59 +08:00
@waiaan #4 第一个有隐式类型转换
CRVV
2019-10-16 10:55:27 +08:00
a 是一个变量,类型是 int[5]

数组是一段连续的内存上放了多个元素,很多语言的数组( std::vector )是一个 struct,包含了这段内存的地址,数组的长度容量这些信息。

但是 C 的数组只是那一段用来放元素的内存,没有其它的东西了,数组的地址,数组本身都是指那一段内存。
stebest
2019-10-16 10:55:37 +08:00
@waiaan 指针不是变量?
stebest
2019-10-16 11:11:08 +08:00
@waiaan 值一样,但类型不一样,移动的步长不一样!数组指针移动一个位置的话,就跳过了整个数组,元素指针移动一个位置,就跳一个元素
summer20100514
2019-10-16 11:31:43 +08:00
opensail
2019-10-16 11:38:30 +08:00
测试结果是 0x7ffd361b7420
0x7ffd361b7420
opensail
2019-10-16 11:44:07 +08:00
@opensail
我得理解 a 是一个指针,指向了数组首元素,第一个输出是指针 a 本身得地址,第二个输出是指针 a 所指向元素得地址,也是数组第一个元素,小白回答,望指教,已收藏问题
waiaan
2019-10-16 11:58:48 +08:00
@opensail

@stebest

我查了一下资料,数组名并不是指针,以前理解错了。
v2bee
2019-10-16 12:12:29 +08:00
《 C 专家编程》里作者说“数组名是指针”的这一页撕下来...
misaka19000
2019-10-16 12:14:30 +08:00
反编译一下,看汇编就清楚了
stebest
2019-10-16 14:04:01 +08:00
@v2bee 确实应该当众处刑
opensail
2019-10-16 14:05:40 +08:00
@stebest 还是 Primer(没有 plus 这本书好,简直是圣经
shfanzie
2019-10-16 15:16:59 +08:00
void main(void)
{
int a[5] = {1, 2, 3, 4, 5};
printf("%p\n", a);
printf("%p\n", &a);
}

printf("%p\n", a); 打印 a 的地址,a 的地址就是它本身,指向 int[5]的地址;
printf("%p\n", &a); 这个地方的&是取址运算符,也就意味着取一个变量的地址并付给指针变量。

所以以上两句打印的同一个地址。
raysonx
2019-10-16 15:55:55 +08:00
好久没答语言相关的问题了。 @stebest 和 9 楼的链接是对的。认同“数组名是指针”的建议把以前看的书撕掉。

C 语言里数组就是数组,在类型上指针是不一样的。当你定义 int arr[10]; 的时候,arr 的类型就是 int[10],sizeof(arr)的结果等于 sizeof(int) * 10 而不是 sizeof(int*)。

问题在于,在很多情况下 C 语言的数组可以退化(decay)成指向第一个(也可以说第 0 个)元素的指针,比如以参数形式传给另一个函数的时候,比如 foo(arr),或者向另一个指针赋值的时候,比如 int *p = arr。这种情况下的 arr 等价于&arr[0]。C 语言的这种特性可以视为隐式类型转换或者语法糖。如果这时你用 sizeof 去测试 p 或者 foo 函数的参数,你会得到等同于 sizeof(int*)的值也就是指针的长度( 32 位系统下为 4,64 位系统下为 8 )。

而 &arr 会返回指向整个数组的指针,类型为 int(*)[10]。因为 C 语言的数组实质就是元素组成的连续内存,所以数组的地址和第一个元素的地址在数值上是相等的,这也是为什么 &arr 在数值上等同于 &arr[0]。但注意它们的类型是不同的。如果你对&arr 进行指针运算,比如 &arr + 1,则计算得到的新地址会指向整个数组之后的下一个字节,而不是指向 arr[1]。
waiaan
2019-10-16 16:21:57 +08:00
@raysonx
赞,谢谢!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/609788

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX