我正在为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中是否有为此提供的库?我应该怎么做?
答案 0 :(得分:1)
您不应将位字段用于任何目的,尤其是不用于内存映射,因为它们的标准化非常差。
您应该做的是使用stdint.h
类型。声明两个uint8_t
变量。通过在声明变量时仔细选择必要的类型,可以节省微控制器中的内存。
例如,在用于有限微控制器的专业程序中,典型的for循环写为for(uint8_t i=0; ...
而不是“草率键入” for(int i=0; ...
。
诀窍是:每当声明 any 变量时,总是考虑变量可能获得的最大值。这样,您可以节省内存并防止溢出错误。
答案 1 :(得分: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都有特殊的指令来提取位域,将其移至低位,并对其进行有符号和无符号扩展,从而将结果扩展到寄存器/可变大小
答案 2 :(得分:0)
您尚未告诉我们您使用的是哪个特定平台,因此我无法为您提供足够详细的答案,但是您想要的是从结构中删除填充。换句话说,您想pack your structs.
这就是我的理解,您希望您的内存布局在一个16位字中为两个字节。
struct {
uint8_t widthValidated;
uint8_t heightValidated;
} status;
To require the compiler创建您可以执行的特定边界:
手臂:
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位)。