Q: If they're so different, then why are array and pointer declarations interchangeable as function formal parameters?
A: It's supposed to be a convenience.
Since arrays decay immediately into pointers, an array is never actually passed to a function. You can pretend that a function receives an array as a parameter, and illustrate it by declaring the corresponding parameter as an array:
	void f(char a[])
	{ ... }
Interpreted literally,
this declaration would have no use,
so
the compiler turns
around and pretends
that you'd written a pointer declaration,
since that's what the function will in fact receive:
	void f(char *a)
	{ ... }
There's nothing
particularly
wrong with talking about a function
as if it
``receives'' an array,
if
the function is traditionally used to operate on 
arrays,
or if
the parameter is naturally treated within the function as an array.
This conversion of array-like declarators into pointers holds only within function formal parameter declarations, nowhere else. If the conversion bothers you, you're under no compulsion to make use of it; many programmers have concluded that the confusion it causes outweighs the small advantage of having the declaration ``look like'' the call or the uses within the function. (Note that the conversion happens only once; something like char a2[][] won't work. See questions 6.18 and 6.19.)
See also question 6.21.
References:
K&R1 Sec. 5.3 p. 95, Sec. A10.1 p. 205
K&R2 Sec. 5.3 p. 100, Sec. A8.6.3 p. 218, Sec. A10.1 p. 226
ISO Sec. 6.5.4.3, Sec. 6.7.1, Sec. 6.9.6
H&S Sec. 9.3 p. 271
CT&P Sec. 3.3 pp. 33-4
Dennis Ritchie, ``The Development of the C Language''