wie bekomme ich den conversion error string literal to 'char*' weg



  • ich habe ein Programm mal versuchsweise mit VS2017 /permissive- kompiliert (oder clang mit -Werror) und bin dabei auf ein static array aus structs gestossen in dessen Initialisierung String Literale nach alter Manier auf char* casts genutzt werden. Ich dachte mit const sollte das erledigt sein aber der Fehler ist dann immer noch da - wie muss ich das richtig deklarieren/definieren?

    struct test
    {
      char* name;
    };
    
    int main()
    {
      static const test test_array[] =
      {
        {"hello"},
        {"bert"}
      };
    
      return 0;
    }
    

    [x86-64 clang 4.0.0] error: conversion from string literal to 'char *' is deprecated [-Werror,-Wc++11-compat-deprecated-writable-strings]

    https://godbolt.org/g/qvWRrE


  • Mod

    Das Ding in Zeile 3 muss ein const char * sein. Die Constness der Struct-Instanzen selbst hat nichts damit zu tun. Beispielsweise könntest du über test_array[0].name[0] immer noch das erste Zeichen des Literals verändern, egal ob test_array[0] selber const ist oder nicht. test_array[0].name[0] müsste const sein, um das zu verbieten. Daher muss test::name ein Zeiger auf konstante chars sein.

    Die Constness der struct-Instanzen verhindert das Verändern von test::name selbst. Aber test::name ist ein Zeiger. Das const verhindert das Verändern des Zeigerwertes, aber nicht das Verändern dessen, worauf der Zeiger zeigt.



  • Die Constness der struct-Instanzen verhindert das Verändern von test::name selbst. Aber test::name ist ein Zeiger. Das const verhindert das Verändern des Zeigerwertes, aber nicht das Verändern dessen, worauf der Zeiger zeigt.

    ich dachte das const wirkt anders auf die Member des struct

    struct S
      int a
      char* b
    
    const S s
    =>
    struct S
      const int a;
      const char* b;
    
    es ist aber
    
    const S s
    =>
    struct S
      int const a;
      char* const b;
    

    das erklärt mein Problem - fühlt sich ein bisschen komisch an (wie ist das in D oder Rust?) - aber trotzdem Danke für die Erklärung



  • Zwischen const int und int const gibt es keinen Unterschied.



  • Zwischen const int und int const gibt es keinen Unterschied.

    das ist klar - wollte es nur verdeutlichen



  • Gast3 schrieb:

    (wie ist das in D oder Rust?)

    In Rust unterscheidet man wie in C++ auch zwischen mutability einer Variablen-Bindung (kann man den Wert einer Variablen nachträglich verändern?) und mutability einer Referenz (bezieht sich auf das, worauf gezeigt wird). So ergeben sich folgende 4 Kombinationen von mutability bei Referenzen:

    let     a : &    i32; // immutable binding, immutable reference
    let mut b : &    i32; //   mutable binding, immutable reference
    let     c : &mut i32; // immutable binding,   mutable reference
    let mut d : &mut i32; //   mutable binding,   mutable reference
    

    Im Gegensatz zu C++ ist die Mutability einer Variablen-Bindung nicht Teil des Typs sondern eine Eigenschaft der "Bindung". Es gibt also kein "mut & i32" als Typ für b .
    Und wenn man eine mutable referenz über eine immutable/shared referenz erreicht, verliert man quasi das "mut":

    let mut x = 42;
    let mr = &mut x; // mutable referenz auf x
    *mr += 1;        // OK, obwohl man mr selbst nicht verändern kann
    
    let rr = &mr;    // shared referenz auf referenz mr
    **rr += 1;       // FEHLER
    

    Das geht ein bisschen in Richtung dessen, was man in D "transitive const" nennt. Ein wichtiges Prinzip in Rust ist, dass es nur einen Weg geben darf, über den man etwas verändern kann (no mutable aliasing).

    In D kenne ich mich nicht wirklich aus. So, wie ich D verstehe, gibt es von den vier genannten C++/Rust Fällen nur drei:

    const int*  a = ...; // const bezieht sich hier auf a und wegen
                         // transitive const damit auch auf *a
                         // Achrung: In C und C++ würde sich das const hier nur
                         // auf *a beziehen, nicht a.
    
    const(int)* b = ...; // const bezieht sich hier nur auf *b, nicht auf b
    
    int*        d = ...; // d und *d beide veränderbar
    

    Fall "c" wie oben gibt es in D wegen "transitive const" nicht. Man müsste es ohne "transitive const" wie a deklarieren und a wäre dann const(const(int)*)


Anmelden zum Antworten