null in std::string -> UB oder OK?
-
dass an einer Stelle ein redundantes '\0' hinten dran sein muss.
dann mach doch dort:
const char* dest = s.c_str();
-
Ist das vom Standard so vorgeschrieben oder sollte ich mich da lieber nicht drauf verlassen?
Ja, ist vorgeschrieben. Das Nullzeichen ist ein Zeichen wie jedes andere auch. Der einzige Kontext, wo es sich bei
std::stringnicht verhaelt wie jedes andere, ist der von nman gezeigte (C-Strings die ohne explizite Laengenangabe an solche Funktionen uebergeben werden).
Das hier duerfte stattdessen ein anderes Ergebnis bringen:auto s = "a"s + string("b\n", 2);Edit: Verdammt, camper

dann mach doch dort
Es ist nicht definiert, dass
s.c_str() == &s[0].
-
Sogar das hier duerfte AFAIR ein anderes Ergebnis bringen:
auto s = "a"s + "b\n"s;(Bin gerade in der Schule, kann das nicht testen, camper du hast doch Clang 3.4?)
Edit: Moment:
If L is a user-defined-string-literal, let str be the literal without its ud-suffix and let len be the number of code units in str (i.e., its length excluding the terminating null character).
Dann klappt das also, nicht wahr?
-
Es ist nicht definiert, dass s.c_str() == &s[0].
hier steht was anderes:
-
weicher schrieb:
hier steht was anderes:
Noe.
Returns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C-string) representing the current value of the string object.
This array includes the same sequence of characters that make up the value of the string object plus an additional terminating null-character ('\0') at the end.
Zudem darf der Inhalte dieses zurueckgegebenen C-Strings nicht veraendert warden.
-
Dobi sagt:
In einem kleinen TCP/IP-Protokoll, dessen Tokens in meiner Software als Strings rumgereicht werden, kommt nun die (unnötige) Anforderung hinzu, dass an einer Stelle ein redundantes '\0' hinten dran sein muss.
Da bei TCP/IP fast immer irgend eine API aufgerufen wird ist IMHO das Wort "unnötig" zurecht in Klammern.
std::string.c_str() doku sagt:
This array includes the same sequence of characters that make up the value of the string object plus an additional terminating null-character ('\0') at the end.
Also macht std::string.c_str() genau das was Dobi will.
-
weicher schrieb:
Da bei TCP/IP fast immer irgend eine API aufgerufen wird ist IMHO das Wort "unnötig" zurecht in Klammern.
Naja, wenn ein Token so aussehen soll:
Startzeichenfolge char[3] -> Anzahl Zeichen char[n] -> Zeichen \0 Endzeichenfolgefinde ich die null schon ziemlich unnötig. Ich würde normal entweder die Anzahl Zeichen vorwegschicken oder nullterminieren, aber nicht beides.
weicher schrieb:
Also macht std::string.c_str() genau das was Dobi will.
Nö, selbst wenn das gehen würde, würde sich die Seuche dann ja auch in den Rest des Programms ausbreiten, weil ich mit char* hantieren müsste. Mit der andereren Lösung bleiben schön alles ein String, nur dass manchmal halt '\0' drin vorkommt, was mich im Rest vom Code aber nicht interessieren muss. Ich finde das so wesentlich schicker.
-
Nö, selbst wenn das gehen würde, würde sich die Seuche dann ja auch in den Rest des Programms ausbreiten, weil ich mit char* hantieren müsste.
Nein, so habe ich das nicht gemeint.
Du kannst im ganzen Programm ganz normal mit dem std::string arbeiten ohne dieses gefrickel mit dem anhängen einer '\0'.
Dann must Du nur genau dort wo ein NULL terminierter string verlangt wird den std::string.c_str() verwenden. Das ist übrigends keine Seuche
die meisten API's verwenden const char* oder char* und genau zu diesem Zweck hat std::string die Funktion c_str()
-
Mal ganz banal:
#include <string> #include <iostream> std::string frame(const std::string& s) { return std::string("start") + s + "ende"; } std::string generateNormal() { return "huhu"; } std::string generateFrickelMist() { std::string s("003bla_"); s.back() = '\0'; return s; } std::string generate() { bool cond( false ); auto s = cond ? generateNormal() : generateFrickelMist(); return frame(s); } void send(const std::string& s) { // Druecks ins Socket. std::cout << s << "\n"; } int main() { for(;;) { auto s = generate(); send( s ); } }Wie wär das jetzt mit std::string.c_str() schöner?
-
Nee, wird nicht schöner

Ich bin davon ausgegangen, dass Du eine struct für einen API Aufruf ausfüllen musst.
-
Arcoth schrieb:
Es ist nicht definiert, dass
s.c_str() == &s[0].Doch.
(Ja, in C++03 ist es nicht explizit definiert, aber de facto eben doch)
-
Die C++-Programmiersprache §20.3.7 schrieb:
[...]im von
c_str()oderdata()reservierten Puffer[...]
-
c++11 schrieb:
Doch.
Ja, das stimmt, seit C++11:
const charT* c_str() const noexcept; const charT* data() const noexcept;Returns: A pointer
psuch thatp + i == &operator[](i)for eachiin[0,size()].In C++03 war das zwar in den Implementierungen praktisch immer der Fall, war aber nicht garantiert.
-
§20.3.7
So einen Paragraphen gibt es nicht
21.3.7 genauso wenig.
-
Hallo Doby,
std::string generateFrickelMist() { std::string s("003bla_"); s.back() = '\0'; return s; }könntest Du auch so machen:
std::string generateFrickelMist() { std::string s("003bla"); s.push_back('\0'); return s; }
-
Oh stimmt, das ist hübscher, danke.
-
Arcoth schrieb:
§20.3.7
So einen Paragraphen gibt es nicht
21.3.7 genauso wenig.Die C++-Programmiersprache §20.3.7
-
Whups! Ich habe gar nicht geschaut, auf was sich das bezieht
