Kerrick Staley
Kerrick Staley

Reputation: 1933

How to cast const uint8_t* to char*

I have a const uint8_t* that I want to convert to a char* for an interface that expects a char*.

The easiest way to do this is with a C-style cast:

const uint8_t* aptr = &some_buffer;
char* bptr = (char*)aptr;

However, our internal style guide (which is based on the Google C++ Style Guide) bans C-style casts.

Another option is this monstrosity, which I find pretty unreadable:

char *cptr = reinterpret_cast<char*>(const_cast<uint8_t*>(aptr));

These other options I tried all failed to compile:

char* dptr = reinterpret_cast<char*>(aptr);
char* eptr = const_cast<char*>(aptr);
char* fptr = static_cast<char*>(aptr);

Is there any way I can perform this cast using a C++-style cast without nesting two separate cast operations?

Upvotes: 6

Views: 14837

Answers (4)

Xirema
Xirema

Reputation: 20396

Another option is this monstrosity, which I find pretty unreadable:

char *cptr = reinterpret_cast<char*>(const_cast<uint8_t*>(aptr));

You might find it unreadable, but this is the idiomatic way to express this conversion in C++.

Here's what's important:

  • You are using a C-style API that, for whatever reason, is not itself const-correct, but you want to preserve the const-correctness of your own code, as much as possible, necessitating a cast to remove the cv-qualifications of the type.
  • The C-style API uses signed data types, whereas your application uses unsigned data types.

In total, those are two conversions that your code needs to make—removing the const-ness, and converting to a signed type. This demands that you make two explicitly expressed conversions, if you want to obey these coding practices. You may not agree with this principle, but your company/coding practices certainly do.

Of course, I don't think anything is stopping you from writing something like this:

char * convert_to_c_data_buffer(uint8_t const* ptr) {
    return reinterpret_cast<char*>(const_cast<uint8_t*>(ptr));
}

char* dptr = convert_to_c_data_buffer(aptr);

Upvotes: 6

Drew Dormann
Drew Dormann

Reputation: 63830

Is there any way I can perform this cast using a C++-style cast without nesting two separate cast operations?

Not portably, no. There is no single "the type is wrong and the const is also wrong" cast.

Another option is this monstrosity, which I find pretty unreadable:

char *cptr = reinterpret_cast<char*>(const_cast<uint8_t*>(ptr));

Do that.

Both C++ casts and your internal style guide are striving to make this look monstrous.

You can prevent the repetition of these casts by writing your own cast.

template< typename T >
char* awful_monster_cast( const T * ptr )
{
    return reinterpret_cast<char*>(const_cast<T*>(ptr));
}

Upvotes: 9

eerorika
eerorika

Reputation: 238391

Is there any way I can perform this cast using a C++-style cast without nesting two separate cast operations?

Certainly. There is no need to nest those cast operations. Instead, you can use two separate expressions:

auto cuint = const_cast<uint8_t*>(aptr);
auto cptr  = reinterpret_cast<char*>(cuint);

Upvotes: 0

NathanOliver
NathanOliver

Reputation: 180805

Is there any way I can perform this cast using a C++-style cast without nesting two separate cast operations?

If you want it done in a single line like char* foo = some_cast(source) then no. The only cast that can remove const is const_cast so you need that plus an additional one to convert that now non const pointer into your source type. That leaves you with the monstrosity

char *cptr = reinterpret_cast<char*>(const_cast<uint8_t*>(aptr));

as the single line solution. This is a safety feature and makes it so it is painfully obvious you are removing constness.

Upvotes: 4

Related Questions