84

I have:

unsigned char *foo();
std::string str;
str.append(static_cast<const char*>(foo()));

The error: invalid static_cast from type ‘unsigned char*’ to type ‘const char*’

What's the correct way to cast here in C++ style?

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
jackhab
  • 17,128
  • 37
  • 99
  • 136
  • 3
    unsigned char has been typically used for holding unicode style strings, are you sure you want to directly cast it rather converting the contents? – Greg Domjan Mar 18 '09 at 16:38

7 Answers7

65

char * and const unsigned char * are considered unrelated types. So you want to use reinterpret_cast.

But if you were going from const unsigned char* to a non const type you'd need to use const_cast first. reinterpret_cast cannot cast away a const or volatile qualification.

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • 4
    "Unrelated" is misleading here: it makes an impression you cannot cast from one to another. I'm reading a draft of 2014, "3.9.1 Fundamental types", and it says: "A `char`, a `signed char`, and an `unsigned char` occupy the same amount of storage and have the same alignment requirement". This IS a relationship. Or here's a more readable link: https://en.cppreference.com/w/cpp/language/types#Character_types – Victor Sergienko Oct 12 '18 at 17:11
57

Try reinterpret_cast

unsigned char *foo();
std::string str;
str.append(reinterpret_cast<const char*>(foo()));
Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
52

reinterpret_cast

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
  • 8
    @jesses.co.tt Thanks for the downvote. The key feature of this post that makes it get upvoted is its timeliness. The other answers provide various detail and are best read and upvoted separately. If [@JaredPars answer](http://stackoverflow.com/a/658924/11635) covers what you're looking for, I'd use that and/or upvote it. You'll note I've invested the time to improve the format of those too. I really don't see the point of expanding this answer to encompass the content of the others. – Ruben Bartelink Aug 20 '13 at 08:38
  • 3
    ok, I understand you're rationale here, and taken as a whole page, I agree that there was no need to re-articulate... I guess it's hard to take the time and look at the entire page and the timestamps instead of judging each answer on its own merit... but point taken (especially from someone who has 55x more reputation from me!) – jesses.co.tt Aug 20 '13 at 16:50
  • 1
    @jesses.co.tt Don't worry, I understand your perspective and you're not far wrong. To be honest it's been a long time since I 'competed' in high traffic tags with fastest-gun-in-the-west responses like this. But you don't get this level of rep by deleting your answer even if that's the right thing to do (which on another day I'd be arguing just as happily!). Right, we have a wall of text cluttering the place, so your mission is accomplished :P – Ruben Bartelink Aug 20 '13 at 22:33
  • 26
    I especially like how you were so concerned with shouting "FIRST!" that you didn't even bother with `basic formatting`. – OJFord Mar 19 '15 at 22:28
  • 8
    This is a truly useless "answer". It simply provides no information. – OYRM Jul 19 '16 at 18:14
  • @RubenBartelink why bother answering then if your answer adds nothing and cannot stand on its own? if you don't see why this answer needs expanding, maybe you should remove it. – Bulbasaur Dec 06 '20 at 06:09
20

unsigned char* is basically a byte array and should be used to represent raw data rather than a string generally. A unicode string would be represented as wchar_t*

According to the C++ standard a reinterpret_cast between unsigned char* and char* is safe as they are the same size and have the same construction and constraints. I try to avoid reintrepret_cast even more so than const_cast in general.

If static cast fails with what you are doing you may want to reconsider your design because frankly if you are using C++ you may want to take advantage of what the "plus plus" part offers and use string classes and STL (aka std::basic_string might work better for you)

AJG
  • 201
  • 2
  • 3
6

Too many comments to make to different answers, so I'll leave another answer here.

You can and should use reinterpret_cast<>, in your case

str.append(reinterpret_cast<const char*>(foo()));

because, while these two are different types, the 2014 standard, chapter 3.9.1 Fundamental types [basic.fundamental] says there is a relationship between them:

Plain char, signed char and unsigned char are three distinct types, collectively called narrow character types. A char, a signed char, and an unsigned char occupy the same amount of storage and have the same alignment requirements (3.11); that is, they have the same object representation.

(selection is mine)

Here's an available link: https://en.cppreference.com/w/cpp/language/types#Character_types

Using wchar_t for Unicode/multibyte strings is outdated: Should I use wchar_t when using UTF-8?

Victor Sergienko
  • 13,115
  • 3
  • 57
  • 91
6

You would need to use a reinterpret_cast<> as the two types you are casting between are unrelated to each other.

Timo Geusch
  • 24,095
  • 5
  • 52
  • 70
-4

Hope it help. :)

const unsigned attribName = getname();
const unsigned attribVal = getvalue();
const char *attrName=NULL, *attrVal=NULL;
attrName = (const char*) attribName;
attrVal = (const char*) attribVal;
joi
  • 307
  • 1
  • 2
  • 11