Is converting uint16_t into uint8_t[2] using a cast valid in C?

91 Views Asked by At

I'm trying to create a function that converts uint16_t into uint8_t[2] in C.

The following code has been tested, but even after reading the disassembly, I'm not sure it's portable or safe.

static inline uint8_t* write_u16(uint16_t in, uint8_t out[2], ArchEndian_t endian) {
    if (NATIVE_ENDIAN != endian){
        in = byte_swap(in);
    } 

    *((uint16_t*)out) = in; //< Is this portable and safe?

    return out; 
} 

How should I think about typecasting in C?

2

There are 2 best solutions below

12
chqrlie On BEST ANSWER

Using a cast for this violates the strict aliasing requirement.

You should instead use memcpy this way:

#include <string.h>
#include <stdint.h>

static inline uint8_t *write_u16(uint16_t in, uint8_t out[2], ArchEndian_t endian) {
    if (NATIVE_ENDIAN != endian) {
        in = byte_swap(in);
    } 
    return memcpy(out, &in, sizeof(in));
} 
3
ikegami On

No. It could violate alignment issues and it violates the strict aliasing requirements.

Use memcpy, shifts or a union. A decent compiler will optimize that to a simple move instruction if possible.

memcpy( out, &in, 2 );