freitass
freitass

Reputation: 6704

Convert struct to unsigned char *

How can I convert the following struct to unsigned char*?

typedef struct {
    unsigned char uc1;
    unsigned char uc2;
    unsigned char uc3;
    unsigned char uc5;
    unsigned char uc6;
} uchar_t;

uchar_t *uc_ptr = new uchar;
unsigned char * uc_ptr2 = static_cast<unsigned char*>(*uc_ptr);
// invalid static cast at the previous line

Upvotes: 2

Views: 11946

Answers (9)

Richard Corden
Richard Corden

Reputation: 21731

One option is to do the reverse. Create your "unsigned char *" buffer first and then use placement new to allocate your object on top of this buffer.

#include <iostream>

struct  uchar_t {
    unsigned char uc1;
    unsigned char uc2;
    unsigned char uc3;
    unsigned char uc4;
    unsigned char uc5;
    unsigned char uc6;
};

int main ()
{
  unsigned char * buffer
    = new unsigned char[ sizeof (uchar_t)/sizeof (unsigned char) ];
  uchar_t * uc = new (buffer) uchar_t ();

  uc->uc3 = 'a';
  std::cout << buffer[2] << std::endl;

  delete buffer;
}

Upvotes: 0

Ari
Ari

Reputation: 3500

Do you want to convert the address of the struct to an address of an unsigned char (as some of the answers assume) or the actual struct to a pointer (as your question indicates)? If the former, here are a few possibilities:

unsigned char * uc_ptr2 = static_cast<unsigned char *>(static_cast<void *>(uc_ptr));
unsigned char * uc_ptr2 = reinterpret_cast<unsigned char *>(uc_ptr);
unsigned char * uc_ptr2 = (unsigned char *)uc_ptr;

If the latter, you can use one of:

unsigned char * uc_ptr2 = *static_cast<unsigned char **>(static_cast<void *>(uc_ptr));
unsigned char * uc_ptr2 = *reinterpret_cast<unsigned char **>(uc_ptr);
unsigned char * uc_ptr2 = *(unsigned char **)uc_ptr;

Upvotes: 0

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 507423

In this case, casting with reinterpret_cast to unsigned char* is guaranteed to work and will point to the first unsigned char data member, because your type is a so-called POD struct (roughly, a C struct).

Quote of the Standard (from 9.2/17, if you wanna look)

A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [Note: There might therefore be unnamed padding within a POD-struct object, but not at its beginning, as necessary to achieve appropriate alignment. ]

So the following works

unsigned char * uc_ptr2 = reinterpret_cast<unsigned char*>(uc_ptr);

Upvotes: 1

Faisal Vali
Faisal Vali

Reputation: 33713

The safest, most portable way to convert POD (i.e. C compatible structs) types to unsigned char pointers is not by using reinterpret_cast but by using static_cast (C++0x fixes this and empowers reinterpret_cast to unambiguously have the same portable semantics as the following line of code):

unsigned char *uc_ptr2 = static_cast<unsigned char*>(static_cast<void*>(uc_ptr));

But for all practical purposes, even though the C++03 standard is thought to be somewhat ambiguous on the issue (not so much when converting pointers of class types, but when converting pointers of non-class types to 'unsigned char*'), most implementations will do the right thing if you do use reinterpret_cast as so:

unsigned char *uc_ptr2 = reinterpret_cast<void*>(uc_ptr);

I suspect that you should be fine with alignment issues since your struct contains unsigned chars which can be aligned at any byte, so the compiler won't insert any packing between the members (but strictly speaking, this is implementation dependent, so use caution).

Upvotes: 1

Jim Buck
Jim Buck

Reputation: 20734

How about simply:

unsigned char * uc_ptr2 = &uc_ptr->uc1;

Upvotes: 1

Mike Kale
Mike Kale

Reputation: 4133

Due to struct packing differences, you can't do this reliably and portably without either using an array to begin with or writing some code that filled a new array one at a time from the struct members by name. A reinterpret_cast might work on one compiler/platform/version and break on another.

You're better off allocating an array on the heap or stack, and then filling it one by one.

Upvotes: 4

smcameron
smcameron

Reputation: 2557

Why would you use such a strange struct instead of:

unsigned char uc[5];

which you can then individually address as uc[0], uc[1], uc[2], uc[3], uc[4] and by pointer to the aggregation (presumably what you want with unsigned char *) by just "uc".

Seems a lot simpler than a struct with multiple unsigned char members that are numbered in the member names (and btw, what happened to uc4? -- another error the array solution would avoid.)

Upvotes: 1

Jared
Jared

Reputation: 6025

You can't use a static_cast here since there is no relationship between the types. You would have to use reinterpret_cast.

Basically, a static_cast should be used in most cases, whereas reinterpret_cast should probably make you question why you are doing it this way.

Here is a time where you would use static_cast:

class Base {
};

class Derived : Base {
};

Base* foo = new Derived;
Derived* dfoo = static_cast<Derived*>( foo );

Whereas here is where you would probably need a reinterpret_cast:

void SetWindowText( WPARAM wParam, LPARAM lParam )
{
   LPCTSTR strText = reinterpret_cast<LPCTSTR>( lParam );
}

Upvotes: 7

John Kugelman
John Kugelman

Reputation: 362187

Try reinterpret_cast<unsigned char*>. static_cast is for converting between compatible types, like a base class to a derived class. reinterpret_cast is for casts between unrelated types.

Upvotes: 2

Related Questions