not - ¿Cómo C++ interpreta un cout con un ''+'' en él?
std::cout significado (5)
Es solo aritmética de punteros. Por ejemplo,
cout << "num" + 1 << endl;
imprimiría una cadena desde ((address of)"num" + 1)
, es decir, "um"
.
Si el valor que agregamos excede la longitud de la cadena, entonces tenemos un comportamiento indefinido.
Me he estado moviendo de un lado a otro con Java / C ++, así que me equivoqué con la salida de mi consola y accidentalmente escribí líneas como:
cout << "num" + numSamples << endl;
cout << "max" + maxSampleValue << endl;
Cada uno de los cuales me dio fragmentos de otras cadenas que tenía en mi programa. Ahora me doy cuenta de mi error, pero ¿qué interpretó C ++ de esas líneas para que produzcan diferentes partes de diferentes cadenas en mi programa?
Hay una simple razón para esto:
"num"
y "max"
son cadenas literal. Su tipo es const char *
. Suponiendo que numSamples
es un entero, lo que está haciendo es aritmética de punteros.
Básicamente está imprimiendo una cadena que apunta a "num"
+ numSamples
bytes.
Si hiciera cout << "num" + 1 << endl
se imprimiría "um"
.
Probablemente lo descubrió, pero la forma correcta de hacerlo es: cout << "num" << numSamples << endl;
Además, usted preguntó:
Pero, ¿cómo interpretó C ++ esas líneas para que produjeran diferentes partes de diferentes cadenas en mi programa?
Como se dijo antes, "num"
es una cadena literal. Generalmente, los literales de cadena se encuentran en el mismo lugar en el programa binario: .rodata
. Todos los demás literales de cadena se ubican en esta región, de modo que cuando avance su puntero una cierta cantidad de bytes, es probable que apunte a otros literales de cadena, por lo que los imprima (parte de ellos).
Tenga en cuenta que aunque iostreams sobrecarga <<
(y >>
) para hacer E / S, estos se definieron originalmente como operadores de cambio de bits. Cuando el compilador analiza la expresión, básicamente ve "operando, operador, operando" y luego verifica si los operandos son de tipos a los que se puede aplicar ese operador.
En este caso, tenemos un literal de cadena y (aparentemente) algún tipo de entero, y el compilador sabe cómo hacer matemáticas en esos (después de convertir el literal de cadena en un puntero).
Desde el punto de vista del compilador, sin embargo, esto no es muy diferente de algo como:
int a, b=1, c=2, d = 3;
a = b << c + d;
La diferencia es que con los operandos de tipo int
, el significado es bastante obvio: se trata de la suma y el desplazamiento de bits. Con iostreams, el significado adjunto a <<
y >>
cambia, pero la sintaxis permitida para ellos en una expresión no cambia.
Desde el "punto de vista" del compilador, la única pregunta es si los operandos a +
son de tipos para los que se permite +
: en este caso, tiene un pointer to char + integer
, por lo que está permitido. El resultado es un puntero a char, y tiene una sobrecarga de <<
que toma un operando de mano izquierda de tipo ostream y un operador de mano derecha de tipo pointer to char
, por lo que la expresión en su conjunto está bien (hasta donde le importa).
si observa operator_precedence , verá que +
se evalúa antes de <<
, lo que deja que se evalúe esta expresión antes de pasarla al operador <<
:
"num" + numSamples
Ahora "num"
va a ser un static const char *
y numSamples
que numSamples
es un tipo integral. Dado que el lado izquierdo del +
es un tipo de puntero y le está agregando, eso es aritmética de punteros. El cout ahora obtiene un puntero a una ubicación en la memoria que es numSamples
o maxSamplueValue
más que la ubicación de "num"
o "max"
. Lo más probable es que todas sus cadenas estáticas estuvieran alineadas en la misma región de la memoria, razón por la cual las vio en lugar de un alboroto aleatorio.
"num"
es char const [4]
. Si numSamples
es entero, el tipo "num" + numSamples
es const char *
. Así que llama al operator <<
cor std::cout
, que se sobrecargó para const char *
e imprime una cadena que comienza desde la dirección ("num") + numSamples en aritmética de punteros.
Prueba esto:
cout << "num" + std::to_string(numSamples) << endl;
cout << "max" + std::to_string(maxSampleValue) << endl;
std::to_string()
que puede encontrar en <string>