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::string
or 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::string
can invalidate the pointer.
Things to Keep in Mind
-
Lifetime
Pointers returned byc_str()
ordata()
remain valid only as long as thestd::string
isn’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.