6

我有一个数组,每个元素可以是 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

这表明它是一个编译器错误。

4

2 回答 2

5

使用 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 个字节,而调试器正确显示了各个字节。

于 2014-11-18T19:15:54.443 回答
1

看起来这个问题已在编译器中修复。我在 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;
}
于 2016-11-30T18:59:55.273 回答