3

std::string.c_str() returns a (const char *) value. I Googled and found that I can do the following:

std::string myString = "Hello World";
char *buf = &myString[0];

How is this possible? &myString[0] is an object of type std::string, so how can this work?

4444
  • 3,541
  • 10
  • 32
  • 43
user1365914
  • 858
  • 2
  • 18
  • 32

7 Answers7

9

&myString[0] is a object of type std::string

No it isn't. myString[0] is a reference to the first character of the string; &myString[0] is a pointer to that character. The operator precedence is such that it means &(myString[0]) and not (&mystring)[0].

Beware that, accessed this way, there's no guarantee that the string will be zero-terminated; so if you use this in a C-style function that expects a zero-terminated string, then you'll be relying on undefined behaviour.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • 1
    "no guarantee that the string will be zero-terminated" true in C++03, but C++11 does have a guarantee. – Tony Delroy Jul 23 '13 at 14:36
  • 6
    @TonyD: No, C++11 doesn't guarantee that the contiguously stored characters will have a zero after them; just that `str[size]` will give a reference to a zero value, and that the result of `c_str()` will be terminated. – Mike Seymour Jul 23 '13 at 14:39
  • @MikeSeymour: I wonder why the spec has made it so complicated. Just to save ONE byte? – Nawaz Jul 23 '13 at 14:45
  • 2
    See 21.4.7.1: `const charT* c_str() const noexcept; const charT* data() const noexcept; Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()].` - so `&p[i]` references within a NUL terminated string (as required by `c_str()`). (You might want to read http://stackoverflow.com/questions/6077189/will-stdstring-always-be-null-terminated-in-c11 ) – Tony Delroy Jul 23 '13 at 14:49
  • @TonyD: Indeed, `c_str()` is required to return a pointer to a contiguous, terminated array (as I said). But `operator[]` is only required to give a reference into a contiguous array for indexes less than `size()`; see 21.4.5/2 amd 21.4.1/5. A suitably perverse implementation could remain unterminated until someone calls `c_str()`. – Mike Seymour Jul 23 '13 at 14:57
  • @MikeSeymour: yikes - it *is* trickier than I thought. Can we close that gap? 21.4.7.1 is a `const` function that doesn't document any change to the observable state of the object, does that leave it the freedom to modify `[size()]` to NUL termination, given if it wasn't previously NUL that would be an observable side effect on the string state? If such things were allowed, it seems to undermine the whole Standard. Separately, I wonder if http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2647.html was endorsed? - that seems to say NUL termination is mandatory for thread safety.... – Tony Delroy Jul 23 '13 at 15:59
  • Further note: if `operator[]` before `c_str()` returned a different address to afterwards, that would itself be an undocumented side effect though arguably a less significant one, and the post-`c_str()` conditions require [size()] to be p + size() so contiguous. Combined with the above, `const` function not changing observable state argument above, that seems to require permanent NUL termination. – Tony Delroy Jul 23 '13 at 16:02
4

There are const and non-const overloads of std::string::operator[]( size_type pos ), and the non-const version returns a char&, so you can do things like

std::string s("Hello");
s[0] = 'Y';

Note that, since s[0] returns char&, then &s[0] is the address of element s[0]. You can assign that address to a char*. It is up to you not to misuse this pointer.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
3

It has to do with operator precedence. The [] operator has higher precedence than the address-of operator &, so the address-of operator works on the character reference returned by the strings operator[] function.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
2

The operator [] (std::string::char& operator[] (size_t pos)) overloaded returns a reference to the character at the index. You are taking the address of such character reference which is fine.

So, myString[0] return type is not std::string but char&.

There is no reason to do it. You can directly do -

myString[0] = 'h';
Mahesh
  • 34,573
  • 20
  • 89
  • 115
2

The std::string methods c_str() and operator[] are two diferent methods, which return two different types.

The method c_str() does indeed return a const char*.

const char* c_str() const;

However, the method operator[] returns instead a reference to a char. When you take the address of it, you get the address of a char.

       char& operator[] (size_t pos);
 const char& operator[] (size_t pos) const;
Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
1

You are wrong. &myString[0] is not of type std::string, it is of type char *.

The [] operator has higher precedence and operator[] returns a reference to char, and its address (the & operator) is of type char *.

Bart Friederichs
  • 33,050
  • 15
  • 95
  • 195
1

The std::string type has an operator[] that allows indexing each one of the characters in the string. The expression myString[0] is a (modifiable) reference to the first character of the string. If you take the address of that you will get a pointer to the first character in the array.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489