Illegal?
-
legal/illegal schei... schrieb:
Hab ne Frage zur Adressierung eines string. Speziell geht es mir um dieses Fützelchen:
&str[0]
Ist das legaler C++ Code?
Soviel ich weiss, garantiert der Standard nicht (zumindest nicht explizit wie bei
std::vector), dassstd::stringintern ein Array speichern muss und man per&str[0]darauf zugreifen kann. Von daher würde ich mich nicht unbedingt darauf verlassen. Du kannst ja direkt überstd::string::operator[]auf die einzelnen Zeichen zugreifen. Oderstd::fill()verwenden. Oderstd::string::assign(). Oder...funz0r schrieb:
aber ob das legal ist, k.a.
Auf gar keinen Fall! Alleine das versteckte Wegcasten der Constness ist böse. Und dann noch
memset()auf einen Speicher anwenden, bei dem du gar nicht weisst, wem er gehört oder wie lange er existiert. Mach das nicht, es gibt wie erwähnt bessere Möglichkeiten.
-
Nexus schrieb:
Du kannst ja direkt über
std::string::operator[]auf die einzelnen Zeichen zugreifen. Oderstd::fill()verwenden. Oderstd::string::assign(). Oder...Das Füllen übernimmt die Windowsfunktion MultiByteToWideChar. Ich dachte mir, ich könnte so ein bisschen Code sparen, wenn ich nicht über dynamische char* gehe.
-
Hm.
Ist bei std::string denn überhaupt garantiert, dass&str[0]einen Zeiger auf eine Array-Repräsentation des Strings liefert? Soweit ich weiss nicht.
Genau dafür gibt es nämlich die Memberfunktionc_str. (Die dann allerdings nur nen const-Zeiger zurückgibt.)Alleine das versteckte Wegcasten der Constness ist böse
Welches const?
Siehe: http://www.cplusplus.com/reference/string/string/operator[]/Man darf sogar ganz offiziell Änderungen über den operator [] machen. Bloss fehlt bei std::string eben die Garantie, wie es sie bei std::vector gibt, dass
&str[0]der Anfang eines zusammenhängenden Speicherbereichs ist, wo alle Elemente hintereinander abgelegt sind.
Etwas formaler: die Garantie dass(&str[N]) == (&str[0]) + N
-
l.i.s schrieb:
Nexus schrieb:
Du kannst ja direkt über
std::string::operator[]auf die einzelnen Zeichen zugreifen. Oderstd::fill()verwenden. Oderstd::string::assign(). Oder...Das Füllen übernimmt die Windowsfunktion MultiByteToWideChar. Ich dachte mir, ich könnte so ein bisschen Code sparen, wenn ich nicht über dynamische char* gehe.
Verwende einen std::vector<char> (bzw. wchar_t) als Puffer, und mach dann so nen String draus:
std::wstring lala() { std::vector<wchar_t> buffer; buffer.resize(initial_size); // ... das ganze MultiByteToWideChar gedöns ... return std::wstring(buffer.begin(), buffer.begin() + result_length); }
-
hustbaer schrieb:
Bloss fehlt bei std::string eben die Garantie, wie es sie bei std::vector gibt, dass
&str[0]der Anfang eines zusammenhängenden Speicherbereichs ist, wo alle Elemente hintereinander abgelegt sind.
Etwas formaler: die Garantie dass(&str[N]) == (&str[0]) + Noh! bedeutet also, das auch wenn ich c_str als parameter übergebe, nicht sicher sein kann, das alle elemente hintereinander liegen?
hmm... dann sollte ich wohl lieber doch ein char* array zwischenschalten`?
-
hustbaer schrieb:
Verwende einen std::vector<char> (bzw. wchar_t) als Puffer, und mach
ah, ok. ist zwar auch ne ganz schöne konvertierungsorgie, aber vermutlich der sicherste weg.
-
hustbaer schrieb:
Alleine das versteckte Wegcasten der Constness ist böse
Welches const?
Das hier, wie gesagt versteckt:
// const // | // v void fill_string ( const char* s, int n ) { // versteckter const_cast! // | // v memset ( (void*)s, 'a', n ); }
-
string bzw wstring ist doch sowieso nur ein Container wie vector für char/wchar_t mit etwas erweiterten Möglichkeiten. Natürlich geht das.
-
Nexus schrieb:
hustbaer schrieb:
Alleine das versteckte Wegcasten der Constness ist böse
Welches const?
Das hier, wie gesagt versteckt:
// const // | // v void fill_string ( const char* s, int n ) { // versteckter const_cast! // | // v memset ( (void*)s, 'a', n ); }oops, sorry

hab nur im kopfposting geguckt.p.S.: ja, die C-style casts sind die schlimmsten!
-
l.i.s schrieb:
hustbaer schrieb:
Bloss fehlt bei std::string eben die Garantie, wie es sie bei std::vector gibt, dass
&str[0]der Anfang eines zusammenhängenden Speicherbereichs ist, wo alle Elemente hintereinander abgelegt sind.
Etwas formaler: die Garantie dass(&str[N]) == (&str[0]) + Noh! bedeutet also, das auch wenn ich c_str als parameter übergebe, nicht sicher sein kann, das alle elemente hintereinander liegen?
hmm... dann sollte ich wohl lieber doch ein char* array zwischenschalten`?nene, c_str() garantiert schon dass alles hintereinander liegt. als input kannst du nen std::(w)string jederzeit verwenden.
bloss als output nicht, da c_str() ja einen const-zeiger zurückgibt. und wegcasten solltest du das const wirklich nicht.
-
Ok, danke!

-
legal/illegal schei... schrieb:
Ich möchte nämlich für eine UTF-8 -> UTF-16LE Konversion die Windowsfunktion MultiByteToWideChar benutzen, und meine Strings auf diese Weise als Parameter übergeben.
Nimm liber gleich nen besseren String als das std::string zeugs
-
*lieber
-
Ok, dieser Beitrag beantwortet nicht die Frage der Legalität. Aber wozu stellt man die Frage überhaupt?!!!
int main() { string str (10,'a'); cout << str << endl; return 0; }Es gibt auch noch
std::fillaus<algorithm>.
-
viel besserer schrieb:
Ok, dieser Beitrag beantwortet nicht die Frage der Legalität. Aber wozu stellt man die Frage überhaupt?!!!
einfach mal alles lesen was er schreibt
-
beantwortet zwar auch nicht die frage nach der legalität, aber die ist ja auch schon geklärt
aber ich glaube nicht (mehr ^^), dass man eine wirklich standard-konforme und effektive string-klasse ohne vector hinbekommt - also wird (obwohl es implementation defined ist) imho der code aus dem TO-post funktionieren.aber ich hab noch immer nicht verstanden, warum der TO nicht mit dem op[] bzw mit iteratoren arbeiten möchte...
bb
-
huestbar schrieb:
Man darf sogar ganz offiziell Änderungen über den operator [] machen. Bloss fehlt bei std::string eben die Garantie, wie es sie bei std::vector gibt, dass &str[0] der Anfang eines zusammenhängenden Speicherbereichs ist, wo alle Elemente hintereinander abgelegt sind.
Etwas formaler: die Garantie dass(&str[N]) == (&str[0]) + NDie Garantie steht in den letzten Working Drafts drin. Und zwar fast genauso:
WD §21.3.1/3 basic_string general requirements schrieb:
The char-like objects in a
basic_stringobject shall be stored contiguously. That is, for anybasic_stringobjects, the identity&*(s.begin() + n) == &*s.begin() + nshall hold for all values of n such that0 <= n < s.size().Und
operator[n]ist definiert über*(begin() + n). Also darf man das inzwischen. Ich weiß aber nicht, wann diese Garantie aufgenommen wurde, sie kam auf jeden Fall später als die fürstd::vector<T>. Es ist auch noch nicht lange her, dass ich zufällig über diese Stelle im Working Draft gestolpert bin.Deswegen habe ich auch einmal vor kurzem an anderer Stelle geschrieben, dass
std::basic_string<T>nur noch ein auf Zeichenketten optimierter, monolithischer Vektor ist. Der Umweg überstd::vector<T>ist also nicht mehr notwendig.Also: Der Code müsste valides C++0x sein, ist aber undefined behaviour in C++98 und C++03.
-
Danke für den Hinweis!
Der Umweg über std::vector<T> ist also nicht mehr notwendig.
Also: Der Code müsste valides C++0x sein, ist aber undefined behaviour in C++98 und C++03.
Naja. Genaugenommen ist der C++03 Standard immer noch der aktuell gültige.
Werd's mir aber für die Zukunft merken
-
Old McDonald schrieb:
Und
operator[n]ist definiert über*(begin() + n). Also darf man das inzwischen.Das allein (also ohne das, was Du vorher geschrieben hast) garantiert allerdings nicht, dass die Elemente hintereinander im Speicher liegen. basic_string<>::begin() muss ja keinen Zeiger zurückgeben.
BTW: Die
&*(s.begin() + n) == &*s.begin() + n-Garantie gibt es scheinbar nicht in C++03 -- sie ist zumindest nicht in N1804 von 2005 drin, wenn ich nichts übersehen habe.Gruß,
SP
-
Ja, das allein nicht. Aber zusammengenommen mit der Garantie, dass
&*begin() + n == &*(begin() + n), folgt natürlich&s[n] == &s[0] + n.In C++03 gab's die Garantie nicht, das ist mir auch aufgefallen, als ich ein wenig gesucht habe. Also ist die Garantie bei
std::vectorälter.