An array is an object in memory. It has an address and a size. It's also true that in certain contexts, an array decays into a pointer to its first element. So numerically, if both a and &a are compared as pointer values, they compare as equal, since they both point to the same address in memory. But they have different data types: a has type int[4] ("array 4 of int"), or int* ("pointer to int") in certain contexts, whereas &a always has type int (*)[4] ("pointer to array 4 of int").
&a points here | V +------+------+------+------+ | a[0] | a[1] | a[2] | a[3] | sizeof(a) == 16 +------+------+------+------+ ^ | &a[0] also points here In certain contexts, 'a' means &a[0]
Hence, (void *)a == (void *)&a.
Also note that because a and &a point to different data types (and in particular, the pointed-to types have different sizes), doing pointer arithmetic will yield different results. a+1 will point to &a[1] (advances by one int value), whereas &a+1 will point to just past the end of the array at &a[4], since it advances by one "array 4 of int" unit:
&a+1 points here | V +------+------+------+------+ | a[0] | a[1] | a[2] | a[3] | +------+------+------+------+ ^ | a+1 points here