Hola:
cuando declaras[] sin valor, lo que estas haciendo es declarando un puntero al lugar de inicio del arreglo, más cuando le declaras un contenido, entonces le estas asignando un valor segun la cantidad de caracteres del contenido, o sea que deja de ser un puntero para ser una cadena (string) cuyo fin está marcado por el caracter de fin de string, que es el '\0'
Aclarando definiciones,
PUNTERO, no asigna lugar físico en memoria para el contenido, sino un lugar de inicio de un conjunto de elementos del mismo tipo que el puntero.
STRING, es un puntero al que se le ha asignado un valor a esos elementos sucesivos (del mismo tipo que el puntero) terminados en el caracter nulo (o fin de string)
http://es.wikipedia.org/wiki/C_string
ARREGLO (o matriz), es un determinado número de igual tipo de elementos donde el que lleva el subindice 0, se comportaría como el puntero al mismo, y los indices subsiguientes se usen o no, ya estan asignados en memoria.
Originalmente el idioma C y el C++ no cuenta con string, pero es posible crearlos mediante un puntero y asignando las posiciones sucesivas, terminandolas en el caracter nulo, donde cada elemento se corresponde con la llamada aritmética de punteros Te paso un link por si querés ahondar en el asunto.
http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_C%2B%2B/Punteros#Aritm.C3.A9tica_de_Punteros
Lo que vos has declarado, como un arreglo, realmente es un tipo especial de arreglo que se usa en C y C++ para los string, por eso no te dá error, pero tiene algunas limitaciones si lo querés usar como un arreglo común, y tiene sus ventajas porque permite usar la libreria string.h para comparar, copiar, invertir concatenar y otras muchas cosas que se hacen con los string pero no con los arreglos.
Dios te bendiga
Saludos
Antonio