14

I want to access starting address of the array that is maintained by the string class.

string str="hey";
char* pointer=(char*)str.c_str();
  1. Is the pointer pointing to the address of the array(maintained by the string class)? or string class will create a new array from dynamic memory and copy the existing string into it and return it's address?

  2. If this is not the right way, then how to access the starting address of the array that is maintained by the string class?

Maroun
  • 94,125
  • 30
  • 188
  • 241
Amit Bhaira
  • 1,687
  • 6
  • 18
  • 31
  • 9
    *Why* do you want this address? What are you trying to do to the string? – trojanfoe Jul 01 '13 at 11:07
  • 1
    Are you looking for a C++11 answer or a C++03 one? The correct answer depends on this. Without further specification, I would further assume C++11. – Sebastian Mach Jul 01 '13 at 11:30
  • Maybe you could answer questions so we can answer your question better? You've been here few minutes ago. – Sebastian Mach Jul 01 '13 at 13:30
  • 1
    @trojanfoe actually I need to find crc of a packet. And the function that is calculating it is written in c. And it needs starting address of the packet. And I am using a string object as a packet. So I need it's starting address so that I can pass it to that function and get my job done. – Amit Bhaira Jul 02 '13 at 09:37
  • 2
    @phresnel I am really sorry sir. I don't even know what version I am working with. I am just working. Is there any API or utility which can tell me the current version, so that i can tell you too. :) – Amit Bhaira Jul 02 '13 at 09:39

5 Answers5

31

In C++11 standard it's explicitly stated that .c_str() (as well as newer .data()) shall return pointer to the internal buffer which is used by std::string.

Any modification of the std::string after obtaining the pointer via .c_str() may result in said char * returned to became invalid (that is - if std::string internally had to reallocate the space).

In previous C++ standards implementation is allowed to return anything. But as standard do not require user to deallocate the result, I've never seen any implementation returning anything newly allocated. At least GNU gcc's and MSVC++'s STL string are internally zero-terminated char arrays, which are returned by c_str().

So it's safe to assume (with normal for C++ caution) that in any version of C++ in any it's implementation .c_str() will return internal buffer.

In other words - you should never ever keep the value of the .c_str() unless you are 100% sure it's won't change it's size anytime in future (unless it's a const, that is).

P.S. BTW, you should never ever do char* pointer=(char*)str.c_str();. It's const char * and you shall not modify the contents, partly because the above - you may end-up overwriting memory of some other object or corrupting internal state of std::string, in case implementation doing something fancy, like indexing characters for faster .find()(newer seen that, but hey - that's an encapsulation!)

Andrian Nord
  • 677
  • 4
  • 11
  • This is exactly the answer I was expecting. – Jun Zhou Jul 01 '13 at 11:21
  • ... and of course modifying a *constant string* will almost certainly have dire circumstances due to where it lives in the process (i.e. probably on a readonly memory page). – trojanfoe Jul 01 '13 at 11:28
  • 1
    @Andrian Nord And if there is 0 probability of resizing then ?? I have created a new string object and the used the resize(512) method. 512 is the maximum length of string possible in my application. Now if I use c_str() to get the address and then use append() method on the object, will it be okay ? – Amit Bhaira Jul 01 '13 at 12:06
  • 1
    It will be ok in at least *current* GNU and Microsoft STL implementations (and probably in any other non-insane implementation). But standard itself say that pointer could be invalidated by any string modifaction, so technically if you want to write RightThing(tm), you probably should not use such a technique. If you want to be 100% sure, you shall probably write your own fixed-size string implementation, or find some already existing. STL is not designed to be fixed-size, so many of your assumptions could be proven wrong in current or any future version of STL implementation you are using. – Andrian Nord Jul 01 '13 at 12:15
  • 1
    copy that .. over and out ..:) – Amit Bhaira Jul 01 '13 at 12:18
  • *as well as newer `.data()`*... not so new, it was there in the previous standard incarnation back from 2003, probably from 1998. – David Rodríguez - dribeas Jul 01 '13 at 13:29
4

NOTE: My answer is only correct for pre-C++11. For C++11, this is the correct answer.


  1. It returns a C-string with null-termination. std::string itself is not null-terminated, so an implementation is allowed to (and probably will) return a newly allocated array of const char. If the creating std::string goes out of scope or if it is mutated, the c_str()-returned string is invalidated.

  2. data() returns the data, but beware it is not a null-terminated string.

In neither case, you are supposed to tweak that data, both data() and c_str() return pointers to const char, and you really shouldn't.

E.g., std::strings are allowed to be reference counted strings (though this is not common anymore) or may even use funky indexing schemes on their data (never seen that, though).

Community
  • 1
  • 1
Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
1

You can get address of the starting of string by char *address = &str[0];. No need to convert string to c-string representation.

Aman Deep Gautam
  • 8,091
  • 21
  • 74
  • 130
  • @PeterWood No, it is not required. – Aman Deep Gautam Jul 01 '13 at 11:11
  • 1
    @davmac I have used it many times. Can you give some reasons, because I can't think of any. – Aman Deep Gautam Jul 01 '13 at 11:12
  • @Aman Deep Gautam: because the standard doesn't mandate it. It may work, or appear to work, in many implementations, but I don't think that it's guaranteed to do so. – davmac Jul 01 '13 at 11:15
  • @davmac I think it does work according to the current standard. – juanchopanza Jul 01 '13 at 11:16
  • @davmac Can you give some references? – Aman Deep Gautam Jul 01 '13 at 11:16
  • 5
    @AmanDeepGautam: "I have used it many times" is never a valid argument in C++ with its huge collection of implementation- and undefined-behaviours. – Sebastian Mach Jul 01 '13 at 11:19
  • @phresnel I know, but that is just a reason to put forward why I gave this answer. Please note that in the same comment I have asked for a reason and in following comments I have also asked for references to read. – Aman Deep Gautam Jul 01 '13 at 11:22
  • No, you shall never do it. MSVC++ implementation of STL `std::string`, for instance, is using internal 16-bytes statically/stack allocated buffer for small strings, which is also used as a pointer in case of large strings (more than 15 bytes of size). It's also known that different versions of MSVC++ strings has different offsets of pointer within said 16-byte buffer (compiler-dependent - it's made via union). – Andrian Nord Jul 01 '13 at 11:28
  • @AndrianNord does doesn't break anything. The buffer is still contiguous, which is the important thing for doing what is suggested in this answer. Where the buffer is located is irrelevant. – R. Martinho Fernandes Jul 01 '13 at 11:29
  • @R. Martinho Fernandes, oh, yes. Sorry, just saw taking the pointer of the object and rushed to tell that this is wrong. Of course, taking the pointer of the first character is essentially the same thing as calling `.c_str()`, except having a lot of additional safety checks and ability to return non-const `char *`, which is highly error-prone, IMO. – Andrian Nord Jul 01 '13 at 11:43
  • @davmac: It is guaranteed to work in C++11, as per 21.4.1/5 and 21.4.5/2 – Benjamin Lindley Jul 01 '13 at 12:11
  • @AmanDeepGautam, C++98 is the relevant reference. As has now been pointed out, C++11 allows your usage. – davmac Jul 01 '13 at 12:20
1

If you actually want the "data" inside the string, then string::data() is the function you are looking for.

Note however, that like c_str(), it is a const pointer to the data - you are not supposed to modify this data.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
0

In C++11, the pointer returned points to the internal array currently used by the string object to store the characters that conform its value.

Refer to http://www.cplusplus.com/reference/string/string/c_str/ for more details.

Jun Zhou
  • 3,060
  • 1
  • 20
  • 31