c++ - una - volatile in c plus plus
¿Por qué ostream imprime `1` para una cadena definida como` volatile char[] `? (4)
Esta pregunta ya tiene una respuesta aquí:
Considera este ejemplo (artificial):
#include <cstdio>
#include <iostream>
int main() {
volatile char test[] = "abc";
std::printf("%s/n", test);
std::cout << test << "/n";
}
Compilarlo con GCC y ejecutarlo da el siguiente resultado:
$ g++ test.cc
$ ./a.out
abc
1
Como puede ver, printf imprime la cadena correctamente mientras que cout imprime 1 . ¿Por qué escribir a cout produce 1 en este caso?
Es el calificador volatile que lo convierte en un bool , intente en su lugar:
std::cout << const_cast<char*>(test) << "/n";
La única sobrecarga adecuada del operator<< es la de bool , por lo que la matriz se convierte (a través de un puntero) a bool , dando como resultado true ya que su dirección no es nula. Esto sale como 1 menos que use el manipulador std::boolalpha .
No puede usar la sobrecarga para const char * que generaría la cadena, o la de const void * que generaría el valor del puntero, ya que esas conversiones requerirán la eliminación del calificador volatile . Las conversiones de puntero implícitas pueden agregar calificadores, pero no pueden quitarlos.
Para generar la cadena, deberías desechar el calificador:
std::cout << const_cast<const char*>(test) << "/n";
pero tenga en cuenta que esto da un comportamiento indefinido ya que se accederá a la matriz como si no fuera volátil.
printf es una función variadica de la vieja escuela, que no ofrece ningún tipo de seguridad. El especificador %s hace que interprete el argumento como const char * , sea lo que sea.
Respuesta encontrada here por una cantidad mínima de búsqueda web:
Respuesta corta:
coutes interpretar el objeto como unbooldebido al calificadorvolatile. Es un capricho de sobrecarga para el operador<<.Respuesta larga: un puntero volátil no se puede convertir en un puntero no volátil sin una conversión explícita, por lo que no se puede usar la sobrecarga
char*nivoid*cuando se llama al operador<<. No hay una sobrecarga calificada volátil, y la coincidencia más cercana es la sobrecargabool, por lo que su matriz se interpreta como un valor booleano en lugar de una dirección o una cadena.Puedes arreglarlo de varias maneras, pero probablemente lo que querías es una conversión explícita:
std::cout<< (char*)test <<std::endl;
(Personalmente lo echaría a const char* .)
std::basic_ostream::operator<< solo tiene una sobrecarga para const char* o const void* que no coincide en este caso, ya que no puede descartar el calificador volátil sin una conversión, esto se trata en el borrador de la sección estándar de C ++ 4.4 Conversiones de calificación que dice:
Un prvalor de tipo "puntero a cv1 T" se puede convertir a un prvalor de tipo "puntero a cv2 T" si "cv2 T" es más cv-calificado que "cv1 T".
por lo tanto, está utilizando la versión bool y, como no es un valor nullptr el resultado es true .
Si elimina el calificador volátil de la test esto proporcionará el resultado que espera. Varias respuestas sugieren utilizar un const_cast para eliminar los calificadores volátiles, pero este es un comportamiento indefinido. Podemos verlo yendo a la sección 7.1.6.1 El párrafo 6 de los calificadores cv que dice:
Si se intenta referirse a un objeto definido con un tipo calificado volátil a través del uso de un valor de gl, con un tipo calificado no volátil, el comportamiento del programa no está definido.
En este caso, const_cast produce un valor predeterminado, pero al eliminar la referencia a ese puntero, se obtiene un valor que invoca un comportamiento indefinido.