Can I cast pointers like this?

104 views Asked by At

Code:

unsigned char array_add[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

...

if ((*((uint32_t*)array_add)!=0)||(*((uint32_t*)array_add+1)!=0))
{
 ...
}

I want to check if the array is all zero. So naturally I thought of casting the address of an array, which also happens to be the address of the first member, to an unsigned int 32 type, so I'll only need to do this twice, since it's a 64 bit, 8 byte array. Problem is, it was successfully compiled but the program crashes every time around here.

I'm running my program on an 8bit microcontroller, cortex-M0.

How wrong am I?

3

There are 3 answers

11
Shiv On

I am not sure but if your array has 8 bytes then just assign base address to a long long variable and compare it to 0. That should solve your problem of checking if the array is all 0.

Edit 1: After Olaf's comment I would say that replace long long with int64_t. However, why do you not a simple loop for iterating the array and checking. 8 chars is all you need to compare.

Edit 2: The other approach could be to OR all elements of array and then compare with 0. If all are 0 then OR will be zero. I do not know whether CMP will be fast or OR. Please refer to Cortex-M0 docs for exact CPU cycles requirement, however, I would expect CMP to be slower.

1
Jack On

In theory this could work but in practice there is a thing you aren't considering: aligned memory accesses.

If a uint32_t requires aligned memory access (eg to 4 bytes), then casting an array of unsigned char which has 1 byte alignment requirement to an uint32_t* produces a pointer to an unaligned array of uint32_t.

According to documentation:

There is no support for unaligned accesses on the Cortex-M0 processor. Any attempt to perform an unaligned memory access operation results in a HardFault exception.

In practice this is just dangerous and fragile code which invokes undefined behavior in certain circumstances, as pointed out by Olaf and better explained here.

0
chux - Reinstate Monica On

To test multiple bytes as once code could use memcmp().

How speedy this is depends more on the compiler as a optimizing compiler may simple emit code that does a quick 8 byte at once (or 2 4-byte) compare. Even the memcmp() might not be too slow on an 8-bit processor. Profiling code helps.

Take care in micro-optimizations, as they too often are not efficient use of coders` time for significant optimizations.

unsigned char array_add[8] = ...
const unsigned char array_zero[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
if (memcmp(array_zero, array_add, 8) == 0) ... 

Another method uses a union. Be careful not to assume if add.arr8[0] is the most or least significant byte.

union {
  uint8_t array8[8];
  uint64_t array64;
} add; 

// below code will check all 8 of the add.array8[] is they are zero.
if (add.array64 == 0)

In general, focus on writing clear code and reserve such small optimizations to very select cases.