"x" 和 C 中的“&x[0]”有什么区别吗?

Is there any difference between "x" and "&x[0]" in C?

浏览一些用 C 编写的软件,我遇到了以下代码,我可以总结如下:

void fill_array_with_some_data(int *_)
{
    // assign some arbitrary int values to _[0] and _[1]
    _[0] = 42;
    _[1] = 24;
}

int main(int argc, char **argv)
{
    int x[2] = {0};
    fill_array_with_some_data(&x[0]);
    
    // do something with the data which is now is x
    if (x[0] & 0x42)
        // do something
    
    return 0;
}

看到 &x[0] 而不是 x 对我来说似乎很奇怪。

两者有区别吗?

有什么理由可以使用 &x[0] 而不是简单地 x 吗?

除了风格之外没有任何区别。

&x[0] 作为参数传递可能表明程序员只希望函数访问第一个元素,而传递 x 则意味着他们希望函数访问整个数组。但这仅仅是约定俗成的,问题中给出的代码示例显然甚至不遵守这一约定。

就语言标准而言,这些表达式是完全等价的,至少在计算上下文中(sizeof 除外):&x[0] 是 shorthand for &*(x + 0),可以简化为&*x,然后是x

fill_array_with_some_data(&x[0])中,x&x[0]是等价的。

int x[2] = {0];之后,x指定一个数组。当在表达式中使用数组时,它将转换为指向其第一个元素的指针,除非:

  • 作为sizeof的操作数,如sizeof x,
  • 它被用作一元&的操作数,如&x,或
  • 它是一个用于初始化数组的字符串文字,如char s[] = "abc";

因此 sizeof x 将给出数组的大小,而 sizeof &x[0] 将给出指向 x.

元素的指针的大小

&x&x[0] 都指向内存中的相同位置,但它们具有不同的类型。 x 的类型是“指向 2 int 的数组的指针”,&x[0] 的类型是“指向 int 的指针”。这意味着 &x + 1 将指向整个数组末尾 x 之后,但 &x[0] + 1 将指向元素 x[0] 之后(因此它指向 x[1] ).

一般情况下,只有在想要具体指向元素时才写&x[0]。当用一些数据填充数组时,程序员应该写 fill_array_with_some_data(x) 来表达他们希望例程对整个数组进行操作。这对编译器没有影响,但它有助于人们理解正在做什么。人们应该只使用 &x[0] 来特别指出该元素。例如,如果一个例程 foo 只对一个元素进行操作,我们可以写 foo(&x[0]) 来向 reader.

表明这一点