【问题标题】:Struct with array issue in C结构与C中的数组问题
【发布时间】:2018-05-28 14:00:35
【问题描述】:

编辑: 使用包含模拟 EEPROM 功能的 Microchip 引导加载程序。
我按照他们的示例声明了一个结构,除了我包含一个数组而不是int somevar&eeVars 被传递给 ezbl.h 中显示的代码 问题是 sizeof 总是产生2,所以只有我的数组的第一个成员是由EZBL_ModifyROM 写入的。如果我将* 添加到EZBL_WriteROMObj 的最后一行,sizeof 会给出正确的结果并且所有内容都已写入。

用于测试数组的 ezbl.h if 语句总是返回 false。我已经测试了一个没有结构的数组,一个结构内的数组(如下所示),一个结构中的 int somevar 和一个结构中的 2 个 int 变量。

照原样,唯一适用于始终为假的 if 语句的情况是单个 int somevar。通过将 * 取消引用添加到 else 案例,一切正常。是否有理由测试数组?这2个箱子有必要吗?

例如,此代码应在第一次上电时打印“65535”,下一次上电时打印“10”,如果数组中的所有值都已写入,则每次后续上电时加 1。

EZBL_AllocFlashHole(emuEEData, 3072, 0x800, -1);
struct
{
 int MY_LUT[101];
} eeVars;

int main(void) {

EZBL_ReadROMObj(&eeVars, EZBL_FlashHoleAddr(emuEEData)); //read the stored data

printf("%d", MY_LUT[10]);

if(eeVars.MY_LUT[10] == 0xFFFF) //check if any values present
{
int i = 0;
for (i=0;i<101;i++)
{MY_LUT[i] = 10;}
}
else
{
MY_LUT[10] = MY_LUT[10] + 1;
}

EZBL_WriteROMObj(EZBL_FlashHoleAddr(emuEEData),&eeVars); //write the data
}

有问题的 ezbl.h 代码

#define EZBL_WriteROMObj(destPgmAddr, srcRAMObjPtr)                                                  
{                                                                                               
    EZBL_NVMKey = 0x03DF;                                                                       
    if(__builtin_types_compatible_p(typeof (srcRAMObjPtr), void*)) //always returns false
/* regular pointer case */   \
    EZBL_ModifyROM((destPgmAddr), (srcRAMObjPtr), sizeof(*srcRAMObjPtr));                   
    else /* array case  */ 
EZBL_ModifyROM((destPgmAddr), (srcRAMObjPtr), sizeof(srcRAMObjPtr));   

}

void EZBL_ModifyROM(unsigned long destPgmAddr, void *srcData, unsigned   int byteLen);

【问题讨论】:

  • 请尝试创建Minimal, Complete, and Verifiable Example 向我们展示。包括一个有效的宏定义,以及它是如何使用的。
  • 您的代码在任何地方都没有使用eeVars...并且该宏将被定义为空,因为它的定义不包含以下行。
  • 这是 Microchip 的代码。 srcRAMobjPtr 是 &eeVars 并且来自插入到 Main 中的一行代码,该代码调用上面显示的 EZBL_WriteROMObj。如果我取消引用 sizeof(srcRAMObjPtr) 中的指针,一切都会正常工作。但那为什么是这 2 种情况呢?
  • 因为您采用 指针 的大小,在 PIC 或 AVR 上为 2 个字节。

标签: c struct embedded


【解决方案1】:

sizeof 如果传入数组,则返回数组的大小(以字节为单位),例如:

int MY_LUT[101];
printf("%d", sizeof(MY_LUT)); //prints 101 * sizeof(int)

如果您传递一个指向包含数组的结构的指针,那么要获得结构的完整大小,您可以取消引用它:

#define EZBL_WriteROMObj(destPgmAddr, srcRAMObjPtr)\
{\
  printf("%d", sizeof(*srcRAMObjPtr));\
}  
...
struct
{
 int MY_LUT[101];
} eeVars;
...
EZBL_WriteROMObj(addr, &eeVars);

如果您知道您的结构将只包含数组而没有其他内容,您可以使用 sizeof(srcRAMObjPtr-&gt;MY_LUT) 获得数组的大小,但这会降低代码的灵活性,当您可以简单地取消引用时,为什么要这样做?指针?


EZBL_WriteROMObj 宏似乎试图判断传递的参数是否为数组,但这是错误的,因为void*struct eevars* 或任何其他指针的类型不同。使用 GNU 扩展检查参数是否为数组的更好方法是:

#define EZBL_WriteROMObj(destPgmAddr, srcRAMObjPtr)\
{\                                            
    if(__builtin_types_compatible_p(typeof(srcRAMObjPtr), typeof(&(srcRAMObjPtr)[0])))\
    {\
        /* regular pointer case */ \
        printf("%d\n", sizeof(*srcRAMObjPtr));\
        EZBL_ModifyROM((destPgmAddr), (srcRAMObjPtr), sizeof(*srcRAMObjPtr));\
    }\
    else /* array case  */ \
    {\
        printf("%d\n", sizeof(srcRAMObjPtr));\
        EZBL_ModifyROM((destPgmAddr), (srcRAMObjPtr), sizeof(srcRAMObjPtr));\
    }\
}

这样,您可以将指针传递给结构或数组:

struct
{
    int MY_LUT[101];
} eeVars;
...
EZBL_WriteROMObj(addr, &eeVars);
/* or: */
EZBL_WriteROMObj(addr, eeVars.MY_LUT);

【讨论】:

  • 是的,我相信你可以将任何你想保存到非易失性内存的东西放入结构中。只要您分配了足够的内存。我已经按照我最初的帖子取消引用指针,然后代码工作正常。但是,为什么 MC 需要这两种情况呢??
  • 啊,刚刚看到了,是的,看起来它正在尝试处理这两种情况并让您传入结构指针或数组,但我认为这不是正确的方法.您可能想要测试它,但我认为您不能将结构指针与这样的 void 指针进行比较。有更好的方法来检查某个东西是否是一个数组。
  • 我已经测试了 1. 一个数组,2. 带有数组成员的结构,如我的第一篇文章 3. 带有 int 变量成员的结构,4. 带有 2 个 int 变量的结构。在所有情况下,if 语句都返回“false”。
  • 您的宏没有正确检查参数是否为数组。查看编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 2018-03-10
  • 2014-11-12
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多