Ну, вы можете попытаться обеспечить , чтобы структура занимала только необходимое вам пространство, с чем-то вроде:
#pragma pack(push, 1)
typedef struct { uint8_t byt[3]; } UInt24;
#pragma pack(pop)
Вы возможно должныпредоставьте эти директивы компилятора (например, строки #pragma
выше), чтобы гарантировать отсутствие заполнения, но это будет , вероятно, по умолчанию для структуры с только восьмибитными полями (a) .
Тогда вам, вероятно, придется упаковывать / распаковывать реальные значения в структуру и из структуры, что-то вроде:
// Inline suggestion used to (hopefully) reduce overhead.
inline uint32_t unpack(UInt24 x) {
uint32_t retVal = x.byt[0];
retval = retVal << 8 | x.byt[1];
retval = retVal << 8 | x.byt[2];
return retVal;
}
inline UInt24 pack(uint32_t x) {
UInt24 retVal;
retVal.byt[0] = (x >> 16) & 0xff;
retVal.byt[1] = (x >> 8) & 0xff;
retVal.byt[2] = x & 0xff;
return retVal
}
Обратите внимание, что это дает значения с прямым порядком байтов независимо от вашей фактической архитектуры.Это не имеет значения, если вы упаковываете и распаковываете сами, но это может стать проблемой, если вы хотите использовать блоки памяти где-либо еще в определенной компоновке (в этом случаеВы можете просто изменить код упаковки / распаковки для использования нужного формата).
Этот метод добавляет небольшой код в вашу систему (и, возможно, минимальное снижение производительности), поэтому вам придется решить, стоит ли этосохранение в используемом пространстве данных.
(a) Например, gcc 7.3
и clang 6.0
показывают 3 6
для следующей программы, показывая, что заполнение отсутствуетв структуре или в следующей структуре:
#include <stdio.h>
#include <stdint.h>
typedef struct { uint8_t byt[3]; } UInt24;
int main() {
UInt24 x, y[2];
printf("%zd %zd\n", sizeof(x), sizeof(y));
return 0;
}
Однако, - это всего лишь пример, поэтому вы можете рассмотреть в интересах переносимого кода использование чего-то вроде #pragma pack(1)
,или вставляя код, чтобы поймать среды, где это может быть не так.