95

I understand c_str converts a string, that may or may not be null-terminated, to a null-terminated string.

Is this true? Can you give some examples?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Amit Singh Tomar
  • 8,380
  • 27
  • 120
  • 199

7 Answers7

107

c_str returns a const char* that points to a null-terminated string (i.e., a C-style string). It is useful when you want to pass the "contents"¹ of an std::string to a function that expects to work with a C-style string.

For example, consider this code:

std::string string("Hello, World!");
std::size_t pos1 = string.find_first_of('w');

std::size_t pos2 = static_cast<std::size_t>(std::strchr(string.c_str(), 'w') - string.c_str());

if (pos1 == pos2) {
    std::printf("Both ways give the same result.\n");
}

See it in action.

Notes:

¹ This is not entirely true because an std::string (unlike a C string) can contain the \0 character. If it does, the code that receives the return value of c_str() will be fooled into thinking that the string is shorter than it really is, since it will interpret \0 as the end of the string.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jon
  • 428,835
  • 81
  • 738
  • 806
  • 1
    Very interesting point you made in Notes: what i would like to know if std::string is already contained \0 then c_str also append \0 at the end of string?? – Amit Singh Tomar Sep 14 '11 at 12:46
  • 3
    @AmitSinghTomar: Yes, so you will have two null bytes -- one which is legitimately part of the string and one which is supposed to be the null terminator. But the c-style function that receives the pointer doesn't know this. – Jon Sep 14 '11 at 12:47
  • Note: a number of C-API will ask for two arguments (`char const*, size_t`), the second being the size, of course. – Matthieu M. Sep 14 '11 at 13:19
  • This is not working: `string str("0.85"); newVolume = _tstof((TCHAR*)str.c_str());` how can i convert TCHAR* argv[] input 0.85 into that? –  Jan 31 '17 at 11:24
  • 1
    @YumYumYum you cannot use `std::string` together with TCHAR stuff, the whole point of TCHAR is to automatically switch between char/wchar while `std::string` works only in terms of char. You will have to use an appropriate abstraction, or just simply don't use TCHAR at all and always do a Unicode build. – Jon Jan 31 '17 at 13:35
  • One possible "appropriate abstraction" is `std::basic_string`. `std::string` is actually a pseudonym for `std::basic_string`. – Peter Feb 05 '17 at 03:34
  • @Jon a stupid question, does using string with c_str cause any performance plenty? i.e if I want to make a desktop application if i used std::string with c_str will the performance be the same as using TCHAR/LPCSTR – ma1169 Dec 01 '18 at 03:59
  • Does c_str() create a copy of the original string? – geschema Jun 05 '19 at 13:11
71

In C++, you define your strings as

std::string MyString;

instead of

char MyString[20];.

While writing C++ code, you encounter some C functions which require C string as parameter.
Like below:

void IAmACFunction(int abc, float bcd, const char * cstring);

Now there is a problem. You are working with C++ and you are using std::string string variables. But this C function is asking for a C string. How do you convert your std::string to a standard C string?

Like this:

std::string MyString;
// ...
MyString = "Hello world!";
// ...
IAmACFunction(5, 2.45f, MyString.c_str());

This is what c_str() is for.

Note that, for std::wstring strings, c_str() returns a const w_char *.

hkBattousai
  • 10,583
  • 18
  • 76
  • 124
9

Most old C++ and C functions, when dealing with strings, use const char*.

With STL and std::string, string.c_str() is introduced to be able to convert from std::string to const char*.

That means that if you promise not to change the buffer, you'll be able to use read-only string contents. PROMISE = const char*

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Daniel Mošmondor
  • 19,718
  • 12
  • 58
  • 99
  • 1
    @There's no such thing as `stl::string`. In fact, there isn't even such a thing as "STL" other than in a museum somewhere. – Kerrek SB Sep 14 '11 at 12:42
  • 1
    @Kerrek SB: STL is (was?) used as a synonym for the C++ standard library. – Peter Mortensen Feb 06 '23 at 00:13
  • Here is [an example](https://stackoverflow.com/questions/17663186/initializing-a-two-dimensional-stdvector/59906780#59906780) from 2020. Or maybe it is due to [old books](https://www.quora.com/Why-do-people-criticise-Yashavant-Kanetkar-books-like-Let-Us-C-Why-dont-more-people-use-Turbo-C)? – Peter Mortensen Feb 06 '23 at 02:06
  • Here is [another example](https://stackoverflow.com/questions/4083712/c-c-string-memory-leaks) (2010) - *"I'm using the STL `string`"* – Peter Mortensen Feb 06 '23 at 03:05
8

In C/C++ programming there are two types of strings: the C strings and the standard strings. With the <string> header, we can use the standard strings. On the other hand, the C strings are just an array of normal chars. So, in order to convert a standard string to a C string, we use the c_str() function.

For example

// A string to a C-style string conversion //

const char *cstr1 = str1.c_str();
cout<<"Operation: *cstr1 = str1.c_str()"<<endl;
cout<<"The C-style string c_str1 is: "<<cstr1<<endl;
cout<<"\nOperation: strlen(cstr1)"<<endl;
cout<<"The length of C-style string str1 = "<<strlen(cstr1)<<endl;

And the output will be,

Operation: *cstr1 = str1.c_str()
The C-style string c_str1 is: Testing the c_str

Operation: strlen(cstr1)
The length of C-style string str1 = 17
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Linkon Ruhul
  • 105
  • 1
  • 6
7

c_str() converts a C++ string into a C-style string which is essentially a null terminated array of bytes. You use it when you want to pass a C++ string into a function that expects a C-style string (e.g., a lot of the Win32 API, POSIX style functions, etc.).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
CadentOrange
  • 3,263
  • 1
  • 34
  • 52
  • 5
    I wouldn't say "converts". Rather, the function "provides access" to a suitable read-only character array -- most likely an array which has always been there in the implementation of `std::string` to begin with. – Kerrek SB Sep 14 '11 at 12:41
6

It's used to make std::string interoperable with C code that requires a null terminated char*.

pmr
  • 58,701
  • 10
  • 113
  • 156
1

You will use this when you encode/decode some string object you transfer between two programs.

Let’s say you use Base64 to encode some array in Python, and then you want to decode that into C++. Once you have the string you decode from Base64-decoded in C++. In order to get it back to an array of float, all you need to do here is:

float arr[1024];
memcpy(arr, ur_string.c_str(), sizeof(float) * 1024);

This is pretty common use, I suppose.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Li haonan
  • 600
  • 1
  • 6
  • 24