giroy
giroy

Reputation: 2243

Converting c pointer types

I have a c pointer to a structre type called uchar4 which looks like

{
    uchar x; 
    uchar y; 
    uchar z; 
    uchar w;
}

I also have data passed in as uint8*. I'd like to create a uchar* pointing to the data at the uint8* so I've tried doing this:

uint8 *data_in;
uchar4 *temp = (uchar4*)data_in;

However, the first 8 bytes always seem to be wrong. Is there another way of doing this?

EDIT:

the input data = 32 43 F6 A8 88 5A 30 8D 31 31 98 A2 E0 37 07 34

the output data = 32 88 31 E0 37 07 34 8D 31 31 98 A2 E0 37 07 34

The first half is always these seemingly random values

Upvotes: 0

Views: 1665

Answers (3)

Grim
Grim

Reputation: 318

Your compiler is aligning the struct members at a four byte boundary. That is why you only get every fourth byte (the rest are assumed to be padding space in the struct). To avoid this behavior you need to declare the struct packed. How it's done depends on the compiler (and not every compiler support it). With GCC you do it like this:

struct uchar4 {
    uchar a;
    uchar b;
    uchar c;
    uchar d;
} __attribute__((__packed__));

Upvotes: 0

msw
msw

Reputation: 43487

Behold, the humble union:

#include <stdio.h>

typedef struct {
    unsigned char x, y, z, w;
} xyzw;

typedef union {
    xyzw x;
    unsigned int i;
} ixyzw;


unsigned int xyzw_to_i(ixyzw *p)
{
    return p->i;
}

int main()
{
    xyzw x = {1, 2, 3, 4};

    printf("sizeof unsigned char %d\n", sizeof(unsigned char));
    printf("sizeof unsigned int  %d\n", sizeof(unsigned int));
    printf("sizeof xyzw          %d\n", sizeof(xyzw));
    printf("sizeof ixyzw         %d\n", sizeof(ixyzw));

    printf("xyzw = { %d, %d, %d, %d }\n", x.x, x.y, x.z, x.w);
    printf("i    = 0x%08x\n", xyzw_to_i((ixyzw *) &x));
    return 0;
}

which on my machine happens to yield:

sizeof unsigned char 1
sizeof unsigned int  4
sizeof xyzw          4
sizeof ixyzw         4
xyzw = { 1, 2, 3, 4 }
i    = 0x04030201

but one can't count on this behavior across compilers or machines.

Upvotes: 1

egrunin
egrunin

Reputation: 25053

  1. If sizeof(uint8) != sizeof(uchar4), then all bets are off.
  2. Do you realize that the bytes of an integer are not necessarily kept (in memory) in the order you expect?

Edited to add This example prints c3 d2 e1 f0. Does that answer your question?

#include <stdio.h>
typedef unsigned char uchar;
typedef struct {
    uchar a;
    uchar b;
    uchar c;
    uchar d;
} uchar4;

int main() {
    int theInt = 0xf0e1d2c3;
    uchar4 *p = (uchar4 *) &theInt;
    printf("%x %x %x %x\n", p->a, p->b, p->c, p->d);
    return 0;
}

Also: if sizeof(uint8) == 8, which of the DWORDs do you want your structure to be mapping?

Upvotes: 1

Related Questions