Передача указателя в массив структур

Это для компилятора MPLABXC8, который я исследовал и нашел ряд связанных тем. Но не смог решить мою проблему. My Array typedef

     typedef volatile struct OneStageOpTag
   {
        unsigned DevID1: 4;
        unsigned SetCmd1 : 4;
        unsigned RdyResponse1 :4;
        unsigned DevID2: 4;
        unsigned SetCmd2 : 4;
        unsigned RdyResponse2 :4;
        unsigned DevID3: 4;
        unsigned SetCmd3 : 4;
        unsigned RdyResponse3 :4;
    }OneStageOpType[3];

Теперь моя переменная

    OneStageOpType CurOperPlan={0};// I checked this one - 
        //-in Simulator 3 element array of structure created

Теперь я передаю указатель на мою функцию

GetOperationSeqForTransportReq(1,1,&CurOperPlan);

ниже функция

void GetOperationSeqForTransportReq(StationIDType SourseStnID,StationIDType DestiStnID,
                    OneStageOpType  *CurTransportPlan)
{
    NOP();
    CurTransportPlan[0]->DevID1=5;  // This is Ok
    CurTransportPlan[1]->DevID1=5;  // This is Not working      
}

только 0-й элемент доступен. Также компилятор жалуется, что указатель структуры передается указателю массива структуры. Я попытался, указав в функции указатель. Похоже, что это указывает на указатель на массив. Мне кажется, что &CurOperPlan адресный указатель только на 0-ую структуру индекса. Весь массив не содержит его. пожалуйста помоги.

3 ответа

Изменить это

GetOperationSeqForTransportReq(1,1,&CurOperPlan);

быть

GetOperationSeqForTransportReq(1, 1, CurOperPlan);

и это

void GetOperationSeqForTransportReq(StationIDType SourseStnID,StationIDType DestiStnID,
                OneStageOpType  *CurTransportPlan)

быть этим

void GetOperationSeqForTransportReq(
  StationIDType SourseStnID,
  StationIDType DestiStnID,
  OneStageOpType CurTransportPlan)

Для полноты также измените это

OneStageOpType CurOperPlan={0};

быть

OneStageOpType CurOperPlan = {{0}};

Внутри функции вам нужно:

(*CurTransportPlan)[0].DevID1=5;  // This is Ok
(*CurTransportPlan)[1].DevID1=5;

Это потому что CurTransportPlan это указатель на ваш массив. Поэтому вы должны разыменовать его, чтобы получить массив. Затем вы можете применить индексирование массива к массиву.

Ссылка на рабочий пример


Чтобы объяснить, почему первый из них работал, мы можем переписать код, применяя преобразования эквивалентности X->Y знак равно (*X).Y, а также X[N] знак равно *(X+N),

Правильная индексация в обозначении массива должна быть CurTransportPlan[0][0].DevID1 а также CurTransportPlan[0][1].DevID1; однако ваш код поменял местами индексы в обоих случаях. Это означало, что первый все еще работал, но второй сломался.


Относительно вашего дизайна кода: было отмечено, что есть два способа передачи массива в функцию:

  1. Вы можете передать указатель на первый элемент массива, как предлагает alk (передавая длину отдельно или жестко ее кодируя)

  2. Вы можете передать указатель на весь массив, как вы делаете в настоящее время.

Я перечислю некоторые различия между этими двумя конструкциями. Используя ваш дизайн, то есть указатель на весь массив:

  • Вы получаете ошибку компиляции, если передан массив с другим количеством строк.
  • Вы получаете ошибку компиляции, если передан энергонезависимый массив.
  • Вы должны написать (*ptr) вместо ptr, что немного более многословно.

Вам нужно принять решение, хотите ли вы, чтобы компилятор выдавал ошибки в этих первых двух пунктах. Ошибок можно избежать путем приведения, но, вообще говоря, необходимость приведения - это признак того, что другой подход был бы лучше.

Если эта функция только когда-либо будет использоваться с размером3volatile массив, то, ИМХО, ваш текущий подход является лучшим, вызывая максимальное обнаружение ошибок компилятором.

Так как у вас есть typedef из трех элементов массива:

typedef volatile struct OneStageOpTag {
  // ...
} OneStageOpType[3];

Проблема выглядит так:

void GetOperationSeqForTransportReq(
  StationIDType SourseStnID,
  StationIDType DestiStnID,
  OneStageOpType *CurTransportPlan)       // HERE

В вышеприведенной функции вы объявляете параметр как указатель на массив из 3 элементов, но вы должны передать его как указатель на первый элемент массива. Это означает, что вы должны сделать следующее:

typedef volatile struct _OneStageOpTag {
  // ...
} Array[3], Element;

// ...

Array CurOperPlan={0};
GetOperationSeqForTransportReq(1,1,&CurOperPlan);

// ...

void GetOperationSeqForTransportReq(StationIDType SourseStnID,
  StationIDType DestiStnID, Element *CurTransportPlan)
{
  NOP();
  CurTransportPlan[0]->DevID1=5;  // This is Ok
  CurTransportPlan[1]->DevID1=5;  // This is Not working      
}

Это должно хорошо работать для вас:)

Другие вопросы по тегам