c - 从闪存中的结构访问数据

标签 c structure avr avr-gcc flash-memory

我正在使用 Atmel AVR 并尝试从存储在闪存(程序)存储器中的结构访问数据。

结构是:

typedef struct {
    uint8_t width;
    uint8_t height; // row number 0 to 5
    uint8_t images; // how many frames does this bitmap have
    uint8_t data[]; // the actual pixel data
} bitmap_t;

数据是:

    __flash   static const bitmap_t bmp_stereo2  = {14,1,1,{126,129,60,66,24,36,60,60,36,24,66,60,129,126}};

我正在尝试访问数据(显示部分代码)...

void lcd_bitmap2(const bitmap_t *bit, uint8_t id, uint8_t posx, uint8_t posy) {
    uint8_t x;
    uint8_t y;  

    const uint8_t bw  = pgm_read_byte(&bit->width);   // this works -- I can print out to serial
    const uint8_t bh  = pgm_read_byte(&bit->height);  //this also works -- I can print out to serial
    // this doesn't work
    const uint8_t  *data = pgm_read_word(&bit->data); // I get: - initialization makes pointer from integer without a cast [enabled by default] 

    const uint8_t  *data = (uint8_t *)pgm_read_word(&bit->data); // this also doen't work (no warning, but wrong data read out)

    //rest of function...

所以我可以访问宽度、高度和图像变量,但不能访问结构的数据部分。 如果我不存储在闪存中,一切都有效——这是我的检索,只有结构的数据数组部分有问题(宽度、高度和图像读取正常)

最佳答案

TL;DR:您不能在标准 C 中安全地执行此操作。

给出这个定义...

typedef struct {
    uint8_t width;
    uint8_t height; // row number 0 to 5
    uint8_t images; // how many frames does this bitmap have
    uint8_t data[]; // the actual pixel data
} bitmap_t;

... bitmap_t.data 是一个“灵活的数组成员”:

As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored. In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply. However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) that would not make the structure larger than the object being accessed [...].

[ C2011 6.7.2.1/18 ;强调]

标准中的示例阐明了为灵活数组成员提供初始值设定项是无效的,就像您的代码试图做的那样。此外,没有理由期望为具有静态或自动存储持续时间的对象(例如您的对象)的灵活数组成员的内容分配任何空间。灵活的数组成员仅在与动态分配的对象结合使用时才有用,除非在实现中做出超出标准要求的 promise 。

因此,访问静态分配对象的灵活数组成员会产生未定义的行为。这与存储的实际位置没有直接关系,尽管 UB 在闪存中时可能表现不同。 (毕竟,该行为是未定义的。)要按照您尝试的方式使用bitmap_t 类型的对象,您将需要修改该类型,使其data 成员具有完整的类型(即固定维度)。

关于c - 从闪存中的结构访问数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53240360/

相关文章:

比较两个以上的字符串

c++ - 如何调用多个slave进行Spi数据传输?

c - gcc -E 不扩展 C11 _Generic 表达式

c - 从 string[strcspn()] 中的指针警告获取整数的情况

c - 在 C 中动态设置数组访问模式

html - 在 HTML 中过度使用有序/无序列表

java - 如何将指针引用地址传递给 JNA 中的结构

c - 函数内绑定(bind)和函数外绑定(bind)的区别

将全局数组复制到另一个全局数组

c - 引脚变化中断 - 外部中断与内部中断