为什么 &array 不等于 &array[0] ?

4

In C:

int a[10];
printf("%p\n", a);
printf("%p\n", &a[0]);

输出结果:

0x7fff5606c600
0x7fff5606c600

这正是我所期望的。现在,在D语言中,我正在尝试这个(显然没有用例,只是闲逛):

int[] slice = [...];
writeln(&slice);
writeln(&slice[0]);

产出结果:

7FFF51600360
10E6E9FE0

为什么会有区别?看起来像是完全不同的内存段。(虽然我刚想到,也许D语言中的数组并不只是相邻分配的整数?)

2
因为“数组”本身就是指向数组的指针。 - kfsone
3个回答

12

在D语言中,数组本质上是一个带有指针和长度字段的结构体,并被视为这样处理。

要获取第一个元素的地址,您可以查询ptr字段。


4
对于动态数组而言,静态长度的数组(例如 int[10])与 C 语言中的数组工作方式相同。 - Adam D. Ruppe
3
你仍然应该使用.ptr来获取指向第一个元素的指针。此外,值得注意的是静态数组作为函数参数传递时是按值传递的,即整个数组会被复制。 - Peter Alexander

3
因为“array”单独使用会解析为指向数组的指针,这使得在使用结构体时可以将指向类型的指针和类型的数组视为类似。
int[] slice = [...];
writeln((cast(void*) slice);
writeln(&slice[0]);

以下内容应该能够满足您的需求。

源自于"C" http://c-faq.com/aryptr/aryptrequiv.html

int[] slice = [...];
int* ptr = &slice[0];

writeln(cast(void*) slice);
writeln(&slice[0]);

// value access
writeln(slice[0]);
writeln(*ptr);
writeln(ptr[0]);

禁止使用C风格的强制类型转换。请改用cast(void*) slice,例如:http://dpaste.dzfl.pl/f708d945 - DejanLekic
我非常确定将切片转换为void*在某个时候会被禁止(或者也许我在某个地方误读了..)。 - Andrej Mitrović

3

很简单 - 动态 D 数组与 C 数组不同。动态 D 数组保存了数组的长度,而 C 数组没有。因此,动态 D 数组不依赖于 NULL 来标记数组的结尾。正如 Adam 在他的评论中指出的那样,静态 D 数组的行为与 C 数组相同。

import std.stdio;

int main() {
  // static array
  int[10] sarr;
  writeln(sarr.length);
  writeln(&sarr);
  writeln(&sarr[0]);

  // dynamic array
  int[] darr = [1, 2, 3];
  writeln(darr.length);
  writeln(&darr);
  writeln(&darr[0]);

  // These are all the same
  writeln(darr.ptr);
  writeln(cast(void*) darr);
  writeln(&darr[0]);

  return 0;
}

(DPaste link: http://dpaste.dzfl.pl/f708d945)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接