Drew
Drew

Reputation: 1

Are there reasons to not type cast pointers (C)?

I'm fairly new to C, feel free to educate...

I am working with a function that is expecting a pointer to a char array as an input. It is quite cumbersome to individually set each element of the array before its call. I have found a couple of alternatives that appear to work, but am concerned that I am stepping into a trap. Below are a couple of options.

Option 1:

 unsigned char DataToPass[8];
 uint64_t *IntPtr = (uint64_t *)DataToPass;
   ...
 *IntPtr = 0x1122334455667788;
 FunctionCall(DataToPass);

Option 2:

unsigned char DataToPass[8];
uint64_t IntData;
...
iDataToPass = 0x1122334455667788;
memcpy(DataToPass, &IntData, sizeof(IntData);
FunctionCall(DataToPass);

Upvotes: 0

Views: 80

Answers (3)

M.M
M.M

Reputation: 141628

Example 1 may cause undefined behaviour due to alignment violation. Also it causes UB by violating the strict aliasing rule.

Example 2 does not cause UB, however it has implementation-defined result. DataToPass[0] would be 0x88 on common systems, but 0x11 and 0x55 also exist, and in fact anything is possible.

My advice would be to write code that clearly expresses your intent:

unsigned char DataToPass[8] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };

It'll take you, what , 10 seconds to type but will save a lot of pain.

Upvotes: 3

Skizz
Skizz

Reputation: 71090

This is a bit dirty but you could use a union.

union Data
{
   char c [8];
   uint64_t i;
};

void Func (char *data);

void test ()
{
  Data d;
  d.i = 0x1122334455667788;
  Func (d.c);
}

I think that'd work. Doesn't get around endian problems though.

(I feel I need to have a really thorough wash now)

Upvotes: 1

Carl Norum
Carl Norum

Reputation: 225032

Both of your examples are fine - with one caveat. You need to ensure that DataToPass is correctly aligned for your system in order for Option 1 to work correctly. Option 2 is fine as is. If you're really looking to type less, why not:

uint64_t IntData = 0x1122334455667788;
FunctionCall((unsigned char *)&IntData);

As @Barmar mentions in his comment, endianness of your system will play a role here as well.

Upvotes: 2

Related Questions