It won't automatically convert (thank god). You'll have to use the method c_str() to get the C string version.

std::string str = "string";
const char *cstr = str.c_str();

.c_str() returns a const char *. If you want a non-const char *, use .data():

std::string str = "string";
char *cstr = str.data();

Some other options:

  • Copying the characters into a vector:

    std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);
    

    Then cstr.data() will give you the pointer.

    This version copies the terminating \0. If you don't want it, remove + 1 or do std::vector<char> cstr(str.begin(), str.end());.

  • Copying into a manually allocated array: (should normally be avoided, as manual memory management is easy to get wrong)

    std::string str = "string";
    char *cstr = new char[str.size() + 1];
    std::strcpy(cstr, str.c_str());
    // do stuff
    delete [] cstr;
    
Answer from orlp on Stack Overflow
🌐
Reddit
reddit.com › r/cpp_questions › howto convert std::string to char**
r/cpp_questions on Reddit: Howto convert std::string to char**
June 17, 2017 -

Hello,

As the title states I am trying to convert an std::string to a char**. Assume I have the following string:

std::string mainString;
mainString += "First Line of Text \n";
mainString += "Second Line of Text \n";
mainString += "Third line of Text \n";

I can parse for '\n' and create a substring easily

int tracker = 0;
for(int i = 0;i<mainString.size();i++){
  if(mainString[i] == '\n'){
  ??? = (char*)mainString.substr(tracker,i-tracker).c_str(); 
  //c_str() returns a const char*, so type cast to char*
  tracker = i;
  }
}

but i don't understand how to go from a char* to a char**

I am creating a few wrapper classes around the CDK widgets. The way that the cdk widgets accept multiple lines of sentences is the following way:

const char *titleMesg[2];
titleMesg[0] = "This is the first line of text";
titleMesg[1] = "This is the second line of text";     
int numberOfLines = 2; 
CDKLABEL *label = newCDKLabel(..., (CDK_CSTRING2)titleMesg, numberOfLines, ...);

where CDK_CSTRING2 type casts to char**.

Let me know if you need additional information

EDIT: I wont be able to respond to this post for a couple of hours.

Discussions

Char to std::string conversion
Your second example works because it is using an assignment operator and not a constructor. std::string aka. basic_string has this assignment operator: basic_string& operator=(value_type __c); This example also works: std::string str; str = 'A'; More on reddit.com
🌐 r/cpp_questions
35
2
May 23, 2024
c++ - How to convert a std::string to const char* or char* - Stack Overflow
How can I convert an std::string to a char* or a const char*? More on stackoverflow.com
🌐 stackoverflow.com
Converting String to Char - C++ Forum
Hello, the code below works but if I remove the " // " to make it no longer a comment and replace the "hello" in the third line with a, it gives me an error. error: cannot convert 'std::__cxx11::string {aka std::__cxx11::basic_string}' to 'char*' in initialization| How can I solve this? More on cplusplus.com
🌐 cplusplus.com
February 22, 2020
How do i turn std::string to char* ?
Use the c_str function, but be aware of lifetimes. More on reddit.com
🌐 r/cpp_questions
31
4
December 31, 2025
🌐
GeeksforGeeks
geeksforgeeks.org › c++ › how-to-convert-std-string-to-char-in-cpp
How to Convert a std::string to char* in C++? - GeeksforGeeks
July 23, 2025 - To convert a std::string to a char*, we can use the std::string:c_str() method that returns a pointer to a null-terminated character array (a C-style string).
🌐
DigitalOcean
digitalocean.com › community › tutorials › convert-string-to-char-array-c-plus-plus
Convert String to Char Array and Char Array to String in C++ | DigitalOcean
August 3, 2022 - Further, we declare an empty array of type char to store the result i.e. result of the conversion of string to char array. Finally, we use strcpy() method to copy the character sequence generated by the c_str() method to the empty char array. ... #include <bits/stdc++.h> using namespace std; ...
🌐
GeeksforGeeks
geeksforgeeks.org › c++ › convert-string-char-array-cpp
Convert String to Char Array in C++ - GeeksforGeeks
January 11, 2025 - Following are the different ways ... to char array, we can first use string::c_str() function to get the underlying character array that contains the string stored in std::string object....
🌐
Wyzant
wyzant.com › resources › ask an expert
std::string to char*? | Wyzant Ask An Expert
August 22, 2019 - If we wanted to manipulate the underlying C string, and then create a new std::string, we would have to duplicate or copy the underlying C string to a new buffer, then construct a new std::string from the modified C string.
Find elsewhere
🌐
Reddit
reddit.com › r/cpp_questions › char to std::string conversion
r/cpp_questions on Reddit: Char to std::string conversion
May 23, 2024 -

Unfortunately for C++ programmers all over the world, there doesn't exist a std::string constructor that simply takes a char, so you're not able to do something like std::string test('A') (does anyone have an explication for this?).

Of course, this leads to super frustrating / non-intuitive behavior and introduces tons of hidden bugs, but it is what it is.

However, I recently discovered the following code snippets, and for the life of me I cannot understand why this works this way, and I was wondering if someone could explain the rationale behind this (tested of both gcc and clang).

If you write :

std::string test = "STRING";
std::string test2 = test[0];

You, (of course, anyone would have guessed I'm sure) get a compilation error, because test[0] returns a char which cannot be converted to a string.

However, if you write :

std::string test = "STRING";
test = test[0];

I would expect the same result, because, well, you're still trying to convert a char to a string. However, to my surprise, this actually compiles and works exactly the way you would expect (test == "S").

Could anyone explains this...?

Top answer
1 of 11
1311

If you just want to pass a std::string to a function that needs const char *, you can use .c_str():

std::string str;
const char * c = str.c_str();

And if you need a non-const char *, call .data():

std::string str;
char * c = str.data();

.data() was added in C++17. Before that, you can use &str[0].

Note that if the std::string is const, .data() will return const char * instead, like .c_str().

The pointer becomes invalid if the string is destroyed or reallocates memory.

The pointer points to a null-terminated string, and the terminator doesn't count against str.size(). You're not allowed to assign a non-null character to the terminator.

2 of 11
225

Given say...

std::string x = "hello";

Getting a `char *` or `const char*` from a `string`

How to get a character pointer that's valid while x remains in scope and isn't modified further

C++11 simplifies things; the following all give access to the same internal string buffer:

const char* p_c_str = x.c_str();
const char* p_data  = x.data();
char* p_writable_data = x.data(); // for non-const x from C++17 
const char* p_x0    = &x[0];

      char* p_x0_rw = &x[0];  // compiles iff x is not const...

All the above pointers will hold the same value - the address of the first character in the buffer. Even an empty string has a "first character in the buffer", because C++11 guarantees to always keep an extra NUL/0 terminator character after the explicitly assigned string content (e.g. std::string("this\0that", 9) will have a buffer holding "this\0that\0").

Given any of the above pointers:

char c = p[n];   // valid for n <= x.size()
                 // i.e. you can safely read the NUL at p[x.size()]

Only for the non-const pointer p_writable_data and from &x[0]:

p_writable_data[n] = c;
p_x0_rw[n] = c;  // valid for n <= x.size() - 1
                 // i.e. don't overwrite the implementation maintained NUL

Writing a NUL elsewhere in the string does not change the string's size(); string's are allowed to contain any number of NULs - they are given no special treatment by std::string (same in C++03).

In C++03, things were considerably more complicated (key differences highlighted):

  • x.data()

    • returns const char* to the string's internal buffer which wasn't required by the Standard to conclude with a NUL (i.e. might be ['h', 'e', 'l', 'l', 'o'] followed by uninitialised or garbage values, with accidental accesses thereto having undefined behaviour).
      • x.size() characters are safe to read, i.e. x[0] through x[x.size() - 1]
      • for empty strings, you're guaranteed some non-NULL pointer to which 0 can be safely added (hurray!), but you shouldn't dereference that pointer.
  • &x[0]

    • for empty strings this has undefined behaviour (21.3.4)
      • e.g. given f(const char* p, size_t n) { if (n == 0) return; ...whatever... } you mustn't call f(&x[0], x.size()); when x.empty() - just use f(x.data(), ...).
    • otherwise, as per x.data() but:
      • for non-const x this yields a non-const char* pointer; you can overwrite string content
  • x.c_str()

    • returns const char* to an ASCIIZ (NUL-terminated) representation of the value (i.e. ['h', 'e', 'l', 'l', 'o', '\0']).
    • although few if any implementations chose to do so, the C++03 Standard was worded to allow the string implementation the freedom to create a distinct NUL-terminated buffer on the fly, from the potentially non-NUL terminated buffer "exposed" by x.data() and &x[0]
    • x.size() + 1 characters are safe to read.
    • guaranteed safe even for empty strings (['\0']).

Consequences of accessing outside legal indices

Whichever way you get a pointer, you must not access memory further along from the pointer than the characters guaranteed present in the descriptions above. Attempts to do so have undefined behaviour, with a very real chance of application crashes and garbage results even for reads, and additionally wholesale data, stack corruption and/or security vulnerabilities for writes.

When do those pointers get invalidated?

If you call some string member function that modifies the string or reserves further capacity, any pointer values returned beforehand by any of the above methods are invalidated. You can use those methods again to get another pointer. (The rules are the same as for iterators into strings).

See also How to get a character pointer valid even after x leaves scope or is modified further below....

So, which is better to use?

From C++11, use .c_str() for ASCIIZ data, and .data() for "binary" data (explained further below).

In C++03, use .c_str() unless certain that .data() is adequate, and prefer .data() over &x[0] as it's safe for empty strings....

...try to understand the program enough to use data() when appropriate, or you'll probably make other mistakes...

The ASCII NUL '\0' character guaranteed by .c_str() is used by many functions as a sentinel value denoting the end of relevant and safe-to-access data. This applies to both C++-only functions like say fstream::fstream(const char* filename, ...) and shared-with-C functions like strchr(), and printf().

Given C++03's .c_str()'s guarantees about the returned buffer are a super-set of .data()'s, you can always safely use .c_str(), but people sometimes don't because:

  • using .data() communicates to other programmers reading the source code that the data is not ASCIIZ (rather, you're using the string to store a block of data (which sometimes isn't even really textual)), or that you're passing it to another function that treats it as a block of "binary" data. This can be a crucial insight in ensuring that other programmers' code changes continue to handle the data properly.
  • C++03 only: there's a slight chance that your string implementation will need to do some extra memory allocation and/or data copying in order to prepare the NUL terminated buffer

As a further hint, if a function's parameters require the (const) char* but don't insist on getting x.size(), the function probably needs an ASCIIZ input, so .c_str() is a good choice (the function needs to know where the text terminates somehow, so if it's not a separate parameter it can only be a convention like a length-prefix or sentinel or some fixed expected length).

How to get a character pointer valid even after x leaves scope or is modified further

You'll need to copy the contents of the string x to a new memory area outside x. This external buffer could be in many places such as another string or character array variable, it may or may not have a different lifetime than x due to being in a different scope (e.g. namespace, global, static, heap, shared memory, memory mapped file).

To copy the text from std::string x into an independent character array:

// USING ANOTHER STRING - AUTO MEMORY MANAGEMENT, EXCEPTION SAFE
std::string old_x = x;
// - old_x will not be affected by subsequent modifications to x...
// - you can use `&old_x[0]` to get a writable char* to old_x's textual content
// - you can use resize() to reduce/expand the string
//   - resizing isn't possible from within a function passed only the char* address

std::string old_x = x.c_str(); // old_x will terminate early if x embeds NUL
// Copies ASCIIZ data but could be less efficient as it needs to scan memory to
// find the NUL terminator indicating string length before allocating that amount
// of memory to copy into, or more efficient if it ends up allocating/copying a
// lot less content.
// Example, x == "ab\0cd" -> old_x == "ab".

// USING A VECTOR OF CHAR - AUTO, EXCEPTION SAFE, HINTS AT BINARY CONTENT, GUARANTEED CONTIGUOUS EVEN IN C++03
std::vector<char> old_x(x.data(), x.data() + x.size());       // without the NUL
std::vector<char> old_x(x.c_str(), x.c_str() + x.size() + 1);  // with the NUL

// USING STACK WHERE MAXIMUM SIZE OF x IS KNOWN TO BE COMPILE-TIME CONSTANT "N"
// (a bit dangerous, as "known" things are sometimes wrong and often become wrong)
char y[N + 1];
strcpy(y, x.c_str());

// USING STACK WHERE UNEXPECTEDLY LONG x IS TRUNCATED (e.g. Hello\0->Hel\0)
char y[N + 1];
strncpy(y, x.c_str(), N);  // copy at most N, zero-padding if shorter
y[N] = '\0';               // ensure NUL terminated

// USING THE STACK TO HANDLE x OF UNKNOWN (BUT SANE) LENGTH
char* y = alloca(x.size() + 1);
strcpy(y, x.c_str());

// USING THE STACK TO HANDLE x OF UNKNOWN LENGTH (NON-STANDARD GCC EXTENSION)
char y[x.size() + 1];
strcpy(y, x.c_str());

// USING new/delete HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY
char* y = new char[x.size() + 1];
strcpy(y, x.c_str());
//     or as a one-liner: char* y = strcpy(new char[x.size() + 1], x.c_str());
// use y...
delete[] y; // make sure no break, return, throw or branching bypasses this

// USING new/delete HEAP MEMORY, SMART POINTER DEALLOCATION, EXCEPTION SAFE
// see boost shared_array usage in Johannes Schaub's answer

// USING malloc/free HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY
char* y = strdup(x.c_str());
// use y...
free(y);

Other reasons to want a char* or const char* generated from a string

So, above you've seen how to get a (const) char*, and how to make a copy of the text independent of the original string, but what can you do with it? A random smattering of examples...

  • give "C" code access to the C++ string's text, as in printf("x is '%s'", x.c_str());
  • copy x's text to a buffer specified by your function's caller (e.g. strncpy(callers_buffer, callers_buffer_size, x.c_str())), or volatile memory used for device I/O (e.g. for (const char* p = x.c_str(); *p; ++p) *p_device = *p;)
  • append x's text to an character array already containing some ASCIIZ text (e.g. strcat(other_buffer, x.c_str())) - be careful not to overrun the buffer (in many situations you may need to use strncat)
  • return a const char* or char* from a function (perhaps for historical reasons - client's using your existing API - or for C compatibility you don't want to return a std::string, but do want to copy your string's data somewhere for the caller)
    • be careful not to return a pointer that may be dereferenced by the caller after a local string variable to which that pointer pointed has left scope
    • some projects with shared objects compiled/linked for different std::string implementations (e.g. STLport and compiler-native) may pass data as ASCIIZ to avoid conflicts
🌐
Cplusplus
cplusplus.com › reference › string › string
std::string
The string class is an instantiation of the basic_string class template that uses char (i.e., bytes) as its character type, with its default char_traits and allocator types (see basic_string for more info on the template). Note that this class handles bytes independently of the encoding used: If used to handle sequences of multi-byte or variable-length characters (such as UTF-8), all members of this class (such as length or size), as well as its iterators, will still operate in terms of bytes (not actual encoded characters).
🌐
Cplusplus
cplusplus.com › forum › beginner › 268303
Converting String to Char - C++ Forum
February 22, 2020 - You still should not go there, but it forces the terminal zero to be placed. string does not use zero terminals, you can in fact do this for fun: string a = "hello\0world"s; cout << a.c_str() << endl; //hello cout << a << endl; //hello world, and on my terminal, the 0 looks like a space but isn't. I used to do a lot of hands-on C string and found out when I moved to strings that you can't mix the two carelessly. ... > Note: to get a pointer which can be used to modify the characters (before the terminating null character), > we have std::string::data() > https://en.cppreference.com/w/cpp/string/basic_string/data constexpr CharT* data() noexcept; //(since C++20) not anymore, it seems
🌐
Reddit
reddit.com › r/cpp_questions › how do i turn std::string to char* ?
r/cpp_questions on Reddit: How do i turn std::string to char* ?
December 31, 2025 -

I need to compile shaders for OpenGL and I need to provide "shaderSource" for that, shaderSource must be char*, but I made a function that reads file contents into a variable, but that variable is an std::string, and I can't convert an std::strings to a char* with (char*), so I made this function

char* FileToChrP(const std::string& FileName) {
    std::ifstream file(FileName, std::ios::binary | std::ios::ate);
    if (!file.is_open()) {
        throw std::runtime_error("Your file is cooked twin | FileToChrP");
    }


    std::streamsize size = file.tellg();
    if (size < 0) throw std::runtime_error("Ur file is cooked twin | FileToChrP");
    file.seekg(0, std::ios::beg);


    char* buffer = new char[size + 1];


    file.read(buffer, size);
    buffer[size] = '\0';


    return buffer;
}char* FileToChrP(const std::string& FileName) {
    std::ifstream file(FileName, std::ios::binary | std::ios::ate);
    if (!file.is_open()) {
        throw std::runtime_error("Your file is cooked twin | FileToChrP");
    }


    std::streamsize size = file.tellg();
    if (size < 0) throw std::runtime_error("Ur file is cooked twin | FileToChrP");
    file.seekg(0, std::ios::beg);


    char* buffer = new char[size + 1];


    file.read(buffer, size);
    buffer[size] = '\0';


    return buffer;
}

but there's a problem, i have to manually delete the buffer with delete[] buffer and that feels wrong.
Also, this seems like a thing that c++ would already have. Is there abetter solution?

🌐
Blogger
aprogrammersday.blogspot.com › 2014 › 10 › c-plus-plus-string-to-char-array.html
A Programmer's Day: c++ string to char array
October 4, 2014 - We will use the strcpy C function, some might argue that this is not true C++ but I say everything from C is in the genesis of C++ so there's nothing untrue to spirit of C++ if we use functions from the C programming language which is the mother of all languages. The new code will look like · using namespace std; #include<string> #include<iostream> int main(int argc, char* argv[]) { std::string strILoveYou = "i<3U"; const char * szMe2 = strILoveYou.c_str(); char * notConstantCharPtr = new char[strILoveYou.length()]; strcpy(notConstantCharPtr, strILoveYou.c_str()); cout << strILoveYou << endl; cout << szMe2 << endl; cout << notConstantCharPtr << endl; return 0; }// highlight with tohtml.com/cpp HAPPY CODING FELLAS!!!
🌐
Cplusplus
cplusplus.com › forum › beginner › 238006
How to convert string to char* and pass - C++ Forum
June 7, 2018 - No, you're converting a string to a char*. There's a difference. You're then storing that char* in an array, for some reason. But, even once you get this right, name isn't a string, it's an array of strings. The point is that name is an array of pointers. A pointer is just a number, and that number is a memory address.
🌐
Scaler
scaler.com › home › topics › what are the differences between c++ char*, std:string, and char[]?
What are the Differences Between C++ Char*, std:string, and Char[]? - Scaler Topics
June 22, 2024 - This is because it forbids converting a string constant to char*. To avoid this warning, we must use the word const. ... In Cpp, we can represent a sequence of characters as an object of the class. This can be done using the std::string.
🌐
Quora
quora.com › How-do-you-convert-const-char-to-std-string-VS19-C-development
How to convert const char [] to std: :string (VS19) (C++, development) - Quora
Answer (1 of 6): char hello[] = “Hello, world”; std::string CppHello = std::string(hello); It’s right there in the documentation.
🌐
DevTut
devtut.github.io › cpp › std-string.html
C++ | std::string
Keep in mind that the pointer is only valid as long as the std::string object is within scope and remains unchanged, that means that only const methods may be called on the object. The data() member function can be used to obtain a modifiable char*, ...
🌐
FavTutor
favtutor.com › blogs › char-to-string-cpp
Convert Char to String in C++ (with code)
November 29, 2023 - Out of all those constructors, the constructor which of particular use to us is this one: ... This constructor is called the fill constructor. It is named so because creating a string using this constructor fills it with n consecutive copies of character c. For example: #include #include using namespace std; int main() { char ch = 'T'; // passing 1 as n string str1(1, ch); // passing 2 as n string str2(2, ch); // printing both the strings cout<<str1<<endl<<str2; }