Структура с проблемой массива в C - PullRequest
0 голосов
/ 28 мая 2018

Отредактировано: Работа с загрузчиком Microchip, который включает эмулированную возможность EEPROM.
Я объявляю структуру согласно их примеру, за исключением того, что я включаю массив вместо int somevar.&eeVars передается в код, показанный в ezbl.h. Проблема в том, что sizeof всегда возвращает 2, так что только первый член моего массива записывается EZBL_ModifyROM.Если я добавлю * в последнюю строку EZBL_WriteROMObj, sizeof даст правильный результат, и все будет написано.

Оператор ezbl.h if для проверки массива всегда возвращает false.Я тестировал массив без структуры, массив внутри структуры (как показано ниже), просто int somevar в структуре и 2 переменные int в структуре.

Как есть, единственный работающий случайс всегда ложным оператором if является единственным int somevar.При добавлении разыменования * к другому случаю все работает.Есть ли причина проверить массив?Есть ли необходимость в 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);

1 Ответ

0 голосов
/ 28 мая 2018

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->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);
...