0

我正在为 16 位微处理器编写一些代码。我的内存非常有限,只有 128 KB。MSP430 的 IAR C/C++ 编译器 我需要实现一些代码来节省一些内存。

我试图用这个 C 特性实现来实现它。

struct {
    unsigned int widthValidated : 1;
    unsigned int heightValidated : 1;
} status;

但有了这段代码,我仍然只使用 16 位字的 1 位。

我的目标是为两个 8 位变量使用相同字长的内存位。第一个变量应该在第二个变量的左边 8 位。

struct {
   unsigned int widthValidated : 8; //8 bits for this
   unsigned int heightValidated : 8; // 8 left over for this
} status;

这可能吗?是否有任何实现,或者 C 中是否有为此的库?我该怎么做呢?

4

3 回答 3

1

您不应该将位域用于任何目的,尤其是内存映射,因为它们的标准化非常差。

你应该做的是使用stdint.h类型。声明两个uint8_t变量。通过在声明变量时仔细选择必要的类型来节省微控制器中的内存。

例如,在有限微控制器的专业程序中,典型的 for 循环被写成for(uint8_t i=0; ...而不是“草率打字” for(int i=0; ...

诀窍是:每当您声明任何变量时,请始终考虑该变量可能获得的最大值是多少。通过这样做,您可以节省内存并防止溢出错误。

于 2019-07-04T13:22:56.823 回答
0

您还没有告诉我们您使用的是哪个特定平台,所以我无法给您足够详细的答案,但您想要的是从结构中删除填充。或者换句话说,你想打包你的结构。

这就是我理解您希望您的内存布局是一个 16 位字中的两个字节的方式。

struct {
    uint8_t widthValidated;
    uint8_t heightValidated;
} status;

要要求编译器创建某个边界,您可以执行以下操作:

手臂:

struct __attribute__((packed)){
    uint8_t widthValidated;
    uint8_t heightValidated;
} status;

对于 gcc:

#pragma pack (1)
struct __attribute__((packed)){
    uint8_t widthValidated;
    uint8_t heightValidated;
} status;

您的平台可能会有所不同,但是当您搜索结构打包时,应该会提出如何执行此操作。

结构内的联合也是一种选择,但这不一定是可移植的,因为位/字节顺序可能因平台而异。

你看我uint8_t在上面使用。这是typedef在里面做的<stdint.h>。这是声明具有定义宽度的整数变量的标准化方法。微控制器内有用的类型是未定义的整数系列:uint8_t(8 位)、uint16_t(16 位)和uint32_t(32 位)。以及它们的签名对应物:int8_t(8 位)、int16_t(16 位)和int32_t(32 位)。

于 2019-07-04T14:26:12.803 回答
0

如果要节省内存,请在声明结构时使用较小的类型

typedef struct
{
    uint8_t flag1: 1;
    uint8_t flag2: 1;
    uint8_t flag3: 1;
    uint8_t flag4: 1;
    uint8_t flag5: 1;
}myflags;

uint8_t foo(myflags f)
{
    return f.flag4;
}

uint8_t foo1(uint8_t flags)
{
    return !!(flags & (1 << 3));
}

void foo3()
{
    printf("%zu\n", sizeof(myflags));
}

它使代码更易于阅读调试和修改。

foo:
        ubfx    r0, r0, #3, #1
        bx      lr
foo1:
        ubfx    r0, r0, #3, #1
        bx      lr
foo3:
        movs    r1, #1
        ldr     r0, .L5
        b       printf
.L5:
        .word   .LC0
.LC0:
        .ascii  "%zu\012\000"

许多 uC 具有提取位域的特殊指令,将它们移动到低位,并将有符号和无符号的结果扩展到寄存器/变量大小

于 2019-07-04T14:18:52.540 回答