variable una plus estatica declarar csharp como c++ string printf iostream volatile

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: cout es interpretar el objeto como un bool debido al calificador volatile . 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* ni void* cuando se llama al operador << . No hay una sobrecarga calificada volátil, y la coincidencia más cercana es la sobrecarga bool , 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.