15

I want an std::string object (such as a name) to a uint8_t array in C++. The function reinterpret_cast<const uint8_t*> rejects my string. And since I'm coding using NS-3, some warnings are being interpreted as errors.

Carlo
  • 323
  • 1
  • 2
  • 13

3 Answers3

35

If you want a pointer to the string's data:

reinterpret_cast<const uint8_t*>(&myString[0])

If you want a copy of the string's data:

std::vector<uint8_t> myVector(myString.begin(), myString.end());
uint8_t *p = &myVector[0];
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • That could in theory not be null terminated – Flexo Oct 05 '11 at 16:28
  • 2
    reinterpret_cast(myString.c_str()) would work though (assuming myString is a std::string). – fbrereto Oct 05 '11 at 16:29
  • @awoodland -- correct, but nul termination was not a requirement of the question. And, given that he wants `uint8_t`, not `char`, it is safe to assume he doesn't want a C-style string. – Robᵩ Oct 05 '11 at 16:31
  • 3
    +1: The `std::vector` is great stuff. Creates a simple copy without memcpy or other C style stuff that likes to pop up in answers to these kinds of questions. – rubenvb Oct 05 '11 at 16:37
  • @Rob: use `.c_str()` instead of `&myString[0]` since `std::string` is not _required_ to be contiguous. – Mooing Duck Oct 05 '11 at 16:40
  • 2
    @awoodland: While in C++03 it might not be null terminated, in C++11 the standard requires null termination of the buffer. – David Rodríguez - dribeas Oct 05 '11 at 16:50
  • @rubenvb: Interstingly, chances are that the code above ends up using `memmove` (maybe even `memcpy`) under the hood. – David Rodríguez - dribeas Oct 05 '11 at 16:51
  • @DavidRodríguez-dribeas - Good point, I'd forgotten that change in amongst all the really obvious ones! – Flexo Oct 05 '11 at 16:56
  • @MooingDuck - Yes, `std::string` is not required to be contiguous, but `std::string::operator[]` is. From [Herb Sutter](http://herbsutter.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/#comment-483): "[C++2003] does require &str[0] to cough up a pointer to contiguous string data (but not necessarily null-terminated!)" See **lib.string.ops** and **lib.string.access**. – Robᵩ Oct 05 '11 at 17:03
  • 1
    @Rob: I was told C++03 did not require it. However, I see it in C++11 at least. §21.4.1 / 5 `...for any basic_string object s, the identity &*(s.begin() + n) == &*s.begin() + n shall hold for all values of n such that 0 <= n < s.size().` – Mooing Duck Oct 05 '11 at 17:12
  • MooingDuck, Rob: C++11 `std::string` has contiguous storage, and if you glue the different parts together (ie the `.c_str()` function has to be O(1), so no copying the buffer), `&s[0]` and the `std::string::data()´ function gives you a null-terminated character array nonetheless. On the other hand, all popular current (pre-c++11) implementations do have contiguous `std::string` storage... – rubenvb Oct 05 '11 at 18:28
  • 1
    David: I know it does that under the hood, it just hides the fragile and unnecessary details away so the code is a lot more readable and bugs for such operations become non-existant. – rubenvb Oct 05 '11 at 18:30
  • 1
    Is there any guarantee that uint8_t has the same representation as char? If not, why is this valid? – Clément Nov 16 '19 at 01:01
13

String objects have a .c_str() member function that returns a const char*. This pointer can be cast to a const uint8_t*:

std::string name("sth");

const uint8_t* p = reinterpret_cast<const uint8_t*>(name.c_str());

Note that this pointer will only be valid as long as the original string object isn't modified or destroyed.

sth
  • 222,467
  • 53
  • 283
  • 367
  • 1
    Is there a way to do it backwards? For example, I would like to cast the uint8_t array to a c_str. Is that possible? – Carlo Jan 05 '12 at 05:15
1

If you need an actual array (not a pointer, as other answers have suggested; the difference is explained very nicely in this answer), you need to use std::copy from <algorithm>:

std::string str = "foo";
uint8_t arr[32];
std::copy(str.begin(), str.end(), std::begin(arr));
kraxor
  • 649
  • 8
  • 16