为什么在单个变量上我需要指定内存地址而在数组上我不需要它?

Why on a single variable I need to specify the memory address while on array I don't need it?

简单example:

double array[] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double *p1 = array;
printf("p1: %f\n", *(p1));

int x = 2;
int* p2 = &x;
printf("p2: %d\n", *p2);

为什么在 p1 上我需要使用 & 而在数组上我不需要在 c/c++ 中使用它?有逻辑上的原因吗?

根据 Bjarne Stroustrup 的书 - Programming: Principles and Practice Using C++ 数组的名称指的是数组的所有元素,例如:

char ar[10];
sizeof(ar) // 10

However, the name of an array turns into ("decays to") a pointer with the slightest excuse.

所以这就是为什么我们可以拥有:char* c = ar。现在 c 被初始化为 &c[0] (即数组的第一个元素)使得 sizeof(c) 4 (取决于实现。

至于变量,它只是一个元素。

因为数组衰减到其声明类型的指针,该指针指向数组包含的第一个元素。

表达式中的数组指示符被转换(极少数例外)为指向其第一个元素的指针。

来自 C 标准(6.3.2.1 左值、数组和函数指示符)

3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

来自C++标准(4.2数组到指针的转换)

1 An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.

因此声明

double *p1 = array;

等同于

double *p1 = &array[0];
            ^^^

考虑这个示范程序

$include <iostream>

int main()
{
    double array[] = { 1000.0, 2.0, 3.4, 17.0, 50.0 };

    std::cout << "sizeof( array ) = " << sizeof( array ) << std::endl;
    std::cout << "sizeof( array + 0 ) = " << sizeof( array + 0 ) << std::endl;
}    

程序输出为

sizeof( array ) = 40
sizeof( array + 0 ) = 8

在第一个输出语句中,数组指示符用作 sizeof 运算符的操作数。所以没有从类型 double[5]double *.

的转换

在第二个输出语句中,数组指示符用在表达式 array + 0 中,后者又用作 sizeof 运算符的操作数。 在这种情况下,存在从类型 double[5] 到类型 double * 的转换。

你可以认为 array 的计算结果是一个 'address' 类型的变量,而 x 是一个 int 类型的变量。 x 存储在内存位置, &x 为您提供该内存位置的地址。

数组的地址,即 &array 将评估为第一个元素的地址,因此也是数组本身的地址。