Was gibt dieser Code auf dem Bildschirm aus?



  • #include <iostream>
    using namespace std;
    
    int main() 
    {
        string s = "hallo";
        const char *a = s.c_str();
        volatile const char *b = s.c_str();
    
        cout << a << endl;
        cout << b << endl;
    
        puts(a);
        puts((const char*)b); // compiled nicht ohne volatile wegzucasten
    
        printf ("%s\n", a);
        printf ("%s\n", b);
    }
    

    6 Zeilen, in denen "hallo" steht, oder? 😉



  • Hm, das hätt ich jetzt auch nicht gedacht.
    Warum wohl?



  • dieNull schrieb:

    Hm, das hätt ich jetzt auch nicht gedacht.
    Warum wohl?

    Ist mir auch ein Rätsel. Aber bestimmt kennt jemand die Antwort.



  • Ah, habs raus. Google is your friend 😛

    void f(const char* ) {}
    
    int main(){
        volatile const char s[] = "hello";
        f(s);
    }
    
    candidate function not viable: no known conversion from 'const volatile char [6]' to 'const char *' for 1st argument
    void f(const char* ) {}
         ^
    

    Und da es bei operator<< des cout's wohl mehrere Überladungen gibt, nimmt er wohl die von bool. Genauso wie wenn man versucht einen Funktionspointer ohne ins void* zu casten auszugeben. Gibt dir auch ne Eins aus.

    Was ich jedoch nicht verstehe, ist warum folgendes jedoch valide ist:

    volatile int x = 10;
    int y = x;
    


  • Wenn man schreibt:

    cout << *b << endl;
    

    kommt ein 'h', wie zu erwarten.
    Aber

    cout << b << endl;
    

    haut nicht hin. Und das hängt mit volatile zusammen. 😞



  • dieNull schrieb:

    Und da es bei operator<< des cout's wohl mehrere Überladungen gibt, nimmt er wohl die von bool.

    Danke, das wird die Erklärung sein. Bei ...

    volatile const char *b = 0;
        cout << b << endl;
    

    ... gibt er 0 aus. Er dereferenziert den Pointer also nicht, was crashen würde.

    Aber irreführend ist das ganze irgendwie schon. Dem operator<< müsste eine Überladung für "volatile char*" spendiert werden. Seltsam, dass das vergessen wurde.



  • dieNull schrieb:

    Was ich jedoch nicht verstehe, ist warum folgendes jedoch valide ist:

    volatile int x = 10;
    int y = x;
    

    y wird mit dem Wert initialisiert, der sich gerade in x befindet. Warum sollte das nicht gehen?



  • Andromeda schrieb:

    y wird mit dem Wert initialisiert, der sich gerade in x befindet. Warum sollte das nicht gehen?

    Na

    volatile const char s[] = "hello";
        const char* p = s;
    

    kompiliert nicht, während das Beispiel von vorhin halt kompiliert.

    Und mit

    volatile int* x = nullptr;
        int* y = x;
    

    das selbe, klappt nicht.

    Also bezieht sich das mit dem "geht nicht" wohl nur auf Pointer.



  • Beachte, wo volatile bei der Zeigerdefinition steht. Hier ist nicht der Zeiger selbst volatile, sondern der Wert, worauf er zeigt, kann flüchtig sein. Weist du ihn einem anderen Zeiger ohne volatile zu, geht der Compiler beim zugreifen über diesen davon aus, dass das Ziel nicht flüchtig ist. volatile ist ein Qualifizierer wie const , der kann nicht einfach implizit weggecastet werden.
    Folgendes ginge:

    char *volatile p = ... //der Zeiger selbst ist volatile, nicht das, worauf er zeigt.
    char *a = p;
    


  • volatile int vi = 42;
    int i = vi;
    

    dasselbe mit zeigern:

    int* volatile vpi = ...;
    int* pi = vpi;
    


  • Ahhh.
    Gerafft, danke.


Anmelden zum Antworten