2012-02-12 12 views
10

He escrito esta sencilla secuencia de comandos para entender qué es una referencia, y me estoy atascando en la matriz de caracteres.Comprensión de la referencia de caracteres

int numbers[5] = {3, 6, 9, 12, 15}; 

for (int i = 0; i < 5; i++) 
{ 
    cout << numbers[i] << endl; 
    cout << &numbers[i] << endl; 
} 

cout << "--------------" << endl; 

char letters[5] = {'a', 'b', 'c', 'd', 'e'}; 

for (int i = 0; i < 5; i++) 
{ 
    cout << letters[i] << endl; 
    cout << &letters[i] << endl; 
} 

y este es el resultado:

3 
0xbffff958 
6 
0xbffff95c 
9 
0xbffff960 
12 
0xbffff964 
15 
0xbffff968 
-------------- 
a 
abcde 
b 
bcde 
c 
cde 
d 
de 
e 

Con la matriz int, cuando uso &numbers[i], recibo un número extraño que es una posición de memoria. Esto esta bien; es exactamente lo que he entendido.

Pero con char, no entiendo por qué tengo esta salida.

+1

Estoy semi sorprendido de que la segunda parte no se rompa al infierno y viceversa, teniendo en cuenta que, en lo que dice el código, 'letters' no tiene nul-terminted. Pero entonces, UB significa que "cualquier cosa puede suceder, incluso el programa aparentemente funciona". – cHao

+2

@cHao: algunos compiladores inicializan cero muchas cosas al compilar en modo de depuración. Tal vez OP fue "afortunado". –

+1

Me sorprende que nadie haya mencionado esto todavía, pero esto no tiene nada que ver con las referencias. Usted está hablando de punteros. –

Respuesta

13

La razón es que cout "sabe" qué hacer con un valor char * - imprime la cadena de caracteres como una cadena C terminada en NUL.

Lo mismo no es cierto para un valor de int *, por lo que cout imprime el valor del puntero en su lugar.

Se puede forzar la salida valor del puntero por colada:

cout << static_cast<void *>(&letters[i]) << endl; 
2

Usted está mirando una peculiaridad de los flujos de C++. Intenta convertir sus argumentos en algo que generalmente se puede imprimir. El tipo de esta expresión es &ints[x]int*. &chars[x] se convierte en char* que es, por cierto, también el tipo de una cadena de caracteres C. Como queremos que este cout << "FOO"' imprima toda la cadena, es necesario tener este comportamiento. En su caso, esto realmente da como resultado un comportamiento indefinido ya que la cadena que está utilizando no termina correctamente. Para resolver este problema, use un static_cast.

2

Cuando pasa al ostream::operator<< (de hecho es una función global, no un operador) el argumento de tipo char*, se considera como una cadena terminada en nulo.

+0

No especifico que el estándar debe ser ASCII. –

+0

@MattiVirkkunen ¡Gracias! –