How can I convert an std::string to a char* or a const char* in C++?
C++ std::string offers a few ways to access the underlying character array. Depending on your needs, you can obtain either a read-only (const char*) pointer or a modifiable (char*) pointer. Below are some common approaches:
1. Using c_str() for a const char*
The simplest way to get a C-style string from an std::string is by using the c_str() member function. This returns a read-only pointer to the string’s data (a null-terminated array of characters).
#include <iostream> #include <string> int main() { std::string cppStr = "Hello World"; const char* cStr = cppStr.c_str(); std::cout << cStr << std::endl; // prints "Hello World" return 0; }
- When to use: Anytime you need a
const char*(e.g., for APIs that only read the data). - Important: The memory pointed to by
c_str()is owned by thestd::string. If the string is modified or goes out of scope, the pointer becomes invalid.
2. Using std::string::data()
C++17 and Older
data()returns aconst char*(same asc_str()). Before C++17, there was no guarantee of a null terminator at the end of the array. With C++17,data()returns the same pointer asc_str(), and both guarantee a null terminator.
std::string s = "Example"; const char* readOnlyPtr = s.data(); // same as s.c_str() in C++17
C++20
data()can return a non-const pointer (char*) when called on a non-conststd::string, allowing you to modify the string contents in place.
#include <iostream> #include <string> int main() { std::string s = "ModifyMe"; #if __cplusplus >= 202002L // C++20 or later char* modifiablePtr = s.data(); modifiablePtr[0] = 'm'; // changes "ModifyMe" to "modifyMe" std::cout << s << std::endl; #endif return 0; }
- When to use: If you need direct, possibly modifiable access to the string’s character array (and you’re on C++20 or newer).
3. Copying into a Separate char* Buffer
If you require a truly independent buffer (e.g., for passing into a C function that might store or modify it beyond the lifetime of your original std::string), you can allocate your own array and copy the data:
#include <iostream> #include <string> #include <cstring> // for std::strcpy int main() { std::string cppStr = "Hello"; // Allocate enough space for the characters + null terminator char* dynamicBuffer = new char[cppStr.size() + 1]; // Copy the string data, including the terminating null std::strcpy(dynamicBuffer, cppStr.c_str()); // dynamicBuffer now holds an independent copy of the string std::cout << dynamicBuffer << std::endl; // Clean up when done delete[] dynamicBuffer; return 0; }
- When to use: If you need a standalone
char*buffer that persists beyond the lifetime of the originalstd::stringor if an API might modify or store it.
4. Using &str[0] or str.data() Pre-C++20 for Modifiable Access
Before C++20, if you need a modifiable array directly in the string’s storage (and you accept that it’s still owned by the string), you can do:
std::string cppStr = "ChangeMe"; char* ptr = &cppStr[0]; // or cppStr.data() in C++17 ptr[0] = 'X';
- Warning: This is valid if the string is non-empty (otherwise
&cppStr[0]is not safe ifsize() == 0). Also, the string remains responsible for this memory—resizing or reassigning thestd::stringcan invalidate the pointer.
Things to Keep in Mind
-
Lifetime
Pointers returned byc_str()ordata()remain valid only as long as thestd::stringisn’t modified or destroyed. -
Ownership
If you need thechar*to outlive thestd::string, you must make a copy of the data (heap allocation or equivalent). -
Modification
c_str()always returns aconst char*.data()returnsconst char*pre-C++20, and can returnchar*in C++20 if called on a non-conststd::string.- Use
&str[0]orstr.data()with caution before C++20 to modify the string contents, ensuring the string is large enough (not empty).
-
Null Terminator
Modern C++ standards (C++11 and beyond) guarantee a null terminator at the end of the string’s character array (forc_str()anddata()), but older compilers might not. Always ensure your environment is up to date if you rely on this behavior.
Summary
- Convert to read-only C string: Use
std::string::c_str()orstd::string::data()(C++17) if you need aconst char*. - Convert to modifiable buffer:
- C++20:
std::string::data()can return achar*. - Pre-C++20: Use
&str[0](only valid if the string is non-empty).
- C++20:
- Create an independent buffer: Dynamically allocate a new array and
std::strcpy()fromc_str().
Why This Matters in Coding Interviews
Converting between std::string and C-style strings is a fundamental skill in C++. Many real-world APIs and libraries still expect or produce char*. Knowing how to navigate these conversions—and understanding ownership and lifetime implications—demonstrates solid C++ proficiency.
Additional Resources
For more advanced C++ features and interview preparation:
- Grokking the Coding Interview: Patterns for Coding Questions – Master the coding patterns that frequently appear in interviews at top tech companies.
- Grokking Data Structures & Algorithms for Coding Interviews – Dive deeper into efficient data handling, essential for high-performance C++ coding.
Explore the DesignGurus YouTube channel for free system design and coding tutorials, or book a Mock Interview with ex-FAANG engineers for personalized interview feedback.