Массив удваивается в размере, если структура определяет как свои слова uint16_t, так и байты uint8_t.
У меня есть массив, каждый элемент которого может быть либо uint16_t, либо пара uint8_t.
Его элементы определены как объединение uint16_t и подмассива 2 uint8_t.
К сожалению, компилятор (MicroChip XC16) выделяет вдвое больше памяти, чем следует для массива.
typedef union {
uint16_t u16; // As uint16_t
uint8_t u8[2]; // As uint8_t
} my_array_t;
my_array_t my_array[1]; // 1 word array, for testing
my_array[0].u8[0] = 1;
my_array[0].u8[1] = 2;
uint8_t byte_0 = my_array[0].u8[0]; // Gets 0x01
uint8_t byte_1 = my_array[0].u8[1]; // Gets 0x02
uint16_t byte_0 = my_array[0].u16; // Gets 0x0201
Компилятор выделяет 4 байта вместо 2 байтов, как и должно быть.
Обходной путь: если я изменю структуру на:
typedef union {
uint16_t u16; // As uint16_t
uint8_t u8[1]; // As uint8_t
} my_array_t;
Компилятор выделяет 2 байта, как и должно быть, но тогда это неверно:
my_array[0].u8[1] = 2;
хотя это все еще работает:
uint8_t byte_1 = my_array[0].u8[1]; // Gets 0x02
(за исключением неудобства, что отладчик не показывает свою ценность).
Вопрос: я должен жить с обходным путем, или я должен использовать лучшее решение?
Пожалуйста, обратитесь к предыдущему обсуждению по этому вопросу, где было предложено вышеуказанное решение.
РЕДАКТИРОВАТЬ.
Согласно предложению EOF (ниже), я проверил sizeof.
Перед обходом:
sizeof(my_array_t) // Is 4
sizeof(my_array[0]) // Is 4
sizeof(my_array[0].u8) // Is 2
После обходного пути:
sizeof(my_array_t) // Is 2
sizeof(my_array[0]) // Is 2
sizeof(my_array[0].u8) // Is 2
Это указывает на то, что это ошибка компилятора.
2 ответа
Вместо массива из 2 байтов используйте структуру из 2 байтов:
// Two bytes in a 16-bit word
typedef struct{
uint8_t lsb; // As uint8_t, LSB
uint8_t msb; // As uint8_t. MSB
} two_bytes_t;
typedef union {
uint16_t u16; // As uint16_t
two_bytes_t u8x2; // As 2 each of uint8_t
} my_array_t;
my_array_t my_array[1]; // 1 word array, for testing
my_array[0].u8x2.msb = 1;
my_array[0].u8x2.lsb = 2;
Компилятор XC16 правильно выделяет только 2 байта для каждого элемента, а отладчик правильно отображает отдельные байты.
Похоже, эта проблема была исправлена в компиляторе. Я проверил это в XC16 1.26 и получил следующие результаты из своего кода (оптимизация 0):
#include "mcc_generated_files/mcc.h"
#include "stddef.h"
typedef union
{
uint16_t u16;
uint8_t u8[2];
} example_1_t;
typedef union
{
uint16_t u16;
struct
{
uint8_t lsb;
uint8_t msb;
};
} example_2_t;
int main(void)
{
SYSTEM_Initialize();
size_t typeSize1 = sizeof (example_1_t); // debugger shows 2
size_t typeSize2 = sizeof (example_2_t); // debugger shows 2
example_1_t ex1; // Can see all values in debugger
ex1.u16 = 0x4321; // u8[0] = 0x21, u8[1] = 0x43
example_2_t ex2; // Can see all values in debugger
ex2.u16 = 0x4321; // lsb = 0x21, msb = 0x43
size_t objSize1 = sizeof (ex1); // debugger shows 2
size_t objSize2 = sizeof (ex2); // debugger shows 2
while (1)
{
}
return -1;
}