¿Son los punteros a, y a, * a, a [0], y a [0] y & a [0] [0]?

Tengo el siguiente programa en C:

#include <stdio.h>

int main(){
    int a[2][2] = {1, 2, 3, 4};
    printf("a:%p, &a:%p, *a:%p \n", a, &a, *a);
    printf("a[0]:%p, &a[0]:%p \n", a[0], &a[0]);
    printf("&a[0][0]:%p \n", &a[0][0]);
    return 0;
}

Da la siguiente salida:

a:0028FEAC, &a:0028FEAC, *a:0028FEAC
a[0]:0028FEAC, &a[0]:0028FEAC
&a[0][0]:0028FEAC

No soy capaz de entender porque son&a, a, *a - Todos idénticos. Lo mismo paraa[0], &a[0] y&a[0][0].

EDITAR:

Gracias a las respuestas, he entendido la razón por la que estos valores se están volviendo iguales. Esta línea del libro porKernighan y Ritchie Resultó ser la clave de mi pregunta:

 the name of an array is a synonym for the location of the initial element.

Entonces, por esto, obtenemos

a = &a[0]y

a[0] = &a[0][0] (considerandoa como una matriz de matrices)

Intuitivamente, ahora la razón está clara detrás de la salida. Pero, considerando cómo se implementan los punteros en C, no puedo entender cómoa y&a son iguales. Estoy asumiendo que hay una variablea en la memoria que apunta a la matriz (y la dirección inicial de esta matriz de bloque de memoria sería el valor de esta variablea).

Pero cuando lo hacemos&a, ¿eso no significa tomar la dirección de la ubicación de memoria donde la variablea fue almacenado? ¿Por qué estos valores son iguales entonces?

Respuestas a la pregunta(8)

Su respuesta a la pregunta