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]
-
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 übertest_array[0].name[0]
immer noch das erste Zeichen des Literals verändern, egal obtest_array[0]
selber const ist oder nicht.test_array[0].name[0]
müsste const sein, um das zu verbieten. Daher musstest::name
ein Zeiger auf konstante chars sein.Die Constness der struct-Instanzen verhindert das Verändern von
test::name
selbst. Abertest::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)*)