Я пытался реализовать функцию, используя сдвиги битов, memcpy
и повторяя каждый байт val
с циклом for, но все мои попытки не сработали ни на одном, нидругой порядок байтов.
Вся арифметика, включая побитовую арифметику, определяется в терминах значений операндов, а не их представлений.Это не может быть достаточно для вас, потому что вы хотите получить результат, который отличается в зависимости от деталей стиля представления для типа uint32_t
.
Вы можете работать с представлениями объектов с помощью различных подходов, но вам все равно нужно знатькакие байты оперируют.Это требует некоторой формы обнаружения.Если big-endian и little-endian являются единственными байтовыми порядками, которые вы хотите поддерживать, то я предпочитаю подход, аналогичный описанному в ответе @P__J __:
void lo_bytes(uint8_t *dest, uint8_t no_bytes, uint32_t val) {
static const union { uint32_t i; uint8_t a[4] } ubytes = { 1 };
memcpy(dest, &val + (1 - ubytes.a[0]) * (4 - no_bytes), no_bytes);
}
Выражение (1 - ubytes.a[0])
оценивается как1, если представление uint32_t
является байтом с прямым порядком байтов, и в этом случае старшие байты появляются в начале представления val
.В этом случае мы хотим пропустить первый 4 - no_bytes
представления и скопировать остальные.Если uint32_t
имеет представление с прямым порядком байтов, с другой стороны, (1 - ubytes.a[0])
будет иметь значение 0, в результате чего memcpy
начинается в начале представления.В любом случае, какие бы байты ни копировались из представления val
, их порядок сохраняется.Вот что memcpy()
делает.