In C++11, we know that std::string
is guaranteed to be both contiguous and null-terminated (or more pedantically, terminated by charT()
, which in the case of char
is the null character 0).
There is this C API I need to use that fills in a string by pointer. It writes the whole string + null terminator. In C++03, I was always forced to use a vector<char>
, because I couldn't assume that string
was contiguous or null-terminated. But in C++11 (assuming a properly conforming basic_string
class, which is still iffy in some standard libraries), I can.
Or can I? When I do this:
std::string str(length);
The string will allocate length+1
bytes, with the last filled in by the null-terminator. That's good. But when I pass this off to the C API, it's going to write length+1
characters. It's going to overwrite the null-terminator.
Admittedly, it's going to overwrite the null-terminator with a null character. Odds are good that this will work (indeed, I can't imagine how it couldn't work).
But I don't care about what "works". I want to know, according to the spec, whether it's OK to overwrite the null-terminator with a null character?
Actually, as of C++11 std::string is guaranteed to be null terminated. Specifically, s[s. size()] will always be '\0' .
Many library functions accept a string or wide string argument with the constraint that the string they receive is properly null-terminated. Passing a character sequence or wide character sequence that is not null-terminated to such a function can result in accessing memory that is outside the bounds of the object.
In C the strings are basically array of characters. In C++ the std::string is an advancement of that array. There are some additional features with the traditional character array. The null terminated strings are basically a sequence of characters, and the last element is one null character (denoted by '\0').
The null character (also null terminator) is a control character with the value zero. It is present in many character sets, including those defined by the Baudot and ITA2 codes, ISO/IEC 646 (or ASCII), the C0 control code, the Universal Coded Character Set (or Unicode), and EBCDIC.
Unfortunately, this is UB, if I interpret the wording correct (in any case, it's not allowed):
§21.4.5 [string.access] p2
Returns:
*(begin() + pos)
ifpos < size()
, otherwise a reference to an object of typeT
with valuecharT()
; the referenced value shall not be modified.
(Editorial error that it says T
not charT
.)
.data()
and .c_str()
basically point back to operator[]
(§21.4.7.1 [string.accessors] p1
):
Returns: A pointer
p
such thatp + i == &operator[](i)
for eachi
in[0,size()]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With