Это будет работать, но memcpy
, за которым следует условный байт , даст вам намного лучший кодген для функции записи.
#include <stdint.h>
#include <string.h>
#define LE (((char*)&(uint_least32_t){1})[0]) // little endian ?
void byteswap(char*,size_t);
uint32_t s2_read_uint32(uint8_t** p)
{
uint32_t value;
memcpy(&value,*p,sizeof(value));
if(!LE) byteswap(&value,4);
return *p+=4, value;
}
void s2_write_uint32(uint8_t** p, uint32_t value)
{
memcpy(*p,&value,sizeof(value));
if(!LE) byteswap(*p,4);
*p+=4;
}
Gcc, начиная с 8-й серии (но не лязг), может устранить эти сдвиги на платформах с прямым порядком байтов, но вы должны помочь ему, restrict
-квалифицируя двояко-косвенный указатель на пункт назначения, иначе он может подумать, что запись в (*p)[0]
может сделать недействительной *p
(uint8_t
- это тип символа и, следовательно, разрешено псевдонимом чего угодно).
void s_write_uint32(uint8_t** restrict p, uint32_t value)
{
(*p)[0] = value & 0xFF;
(*p)[1] = (value >> 8 ) & 0xFF;
(*p)[2] = (value >> 16) & 0xFF;
(*p)[3] = value >> 24;
*p += 4;
}