En C, el nombre de la matriz denota la dirección del elemento cero de la matriz. ¿Es esto solo una regla, o tiene alguna razón asociada?

En C, el nombre de la matriz denota la matriz, no cualquier tipo de dirección.

También en C, ciertos tipos son implícitamente convertibles a otros tipos, y esas conversiones se invocan en situaciones en las que un tipo no es aceptable, pero uno de los tipos a los que es convertible es:

Aquí uso un doble donde los dobles no están permitidos, pero los ints son:

doble d = 3.15;
int n = d; // el nombre del doble no denota un número entero
// esto es una abreviatura de int n = trunc (d);

Aquí uso una matriz donde las matrices no están permitidas, pero los punteros son:

int a [10];
int * p = a; // el nombre de la matriz no denota un puntero
// esto es una abreviatura de int * p = & a [0];

C en realidad no tiene muchas situaciones en las que las matrices sean aceptables (C ++ tiene toneladas más, pero se trata de C), solo tiene dos:

int (* p2) [10] = & a; // no hay conversión de matriz a puntero aquí
printf (“% zu \ n”, tamaño de a); // no hay conversión de matriz a puntero aquí

En cuanto a la razón detrás de su conversión … C fue creado como una evolución de un lenguaje de programación más antiguo llamado B. En B, el nombre de una matriz era en realidad un puntero. La declaración “a [10];” creó un puntero llamado “a”, y también creó una matriz sin nombre de 10 palabras, y también colocó la dirección del primer elemento de esa matriz en el puntero.

Cuando C inventó las estructuras, dmr se dio cuenta de que las matrices de estilo B no se pueden usar: struct {int a, int a [10]; } sería una estructura con un int y un puntero y la matriz tendría que existir en otro lugar (¿en el montón?), por lo que no podría, digamos, leer 22 bytes en la memoria y tratarlos con un valor de ese estructura Así que hizo el mayor cambio de ruptura entre B y C: las matrices ya no eran punteros. La declaración “int a [10];” crea solo la matriz, nada más. Pero todo el código B existente arrojó las “matrices” de B utilizando semántica de puntero, por lo que agregó esta conversión como un truco inteligente para que sea posible compilar casi todo el código B como C.

El índice de un elemento en una matriz se calcula como startaddress + index * elementize.

Entonces señalar al primer elemento es 100% lógico y correcto.

La dirección de A [x] es & A + x * sizeof (cada elemento de la matriz), entonces, la dirección de A [0] es & A + 0 * sizeof (lo que sea), o la dirección de A.