Передача указателя в массив структур
Это для компилятора 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
; однако ваш код поменял местами индексы в обоих случаях. Это означало, что первый все еще работал, но второй сломался.
Относительно вашего дизайна кода: было отмечено, что есть два способа передачи массива в функцию:
Вы можете передать указатель на первый элемент массива, как предлагает alk (передавая длину отдельно или жестко ее кодируя)
Вы можете передать указатель на весь массив, как вы делаете в настоящее время.
Я перечислю некоторые различия между этими двумя конструкциями. Используя ваш дизайн, то есть указатель на весь массив:
- Вы получаете ошибку компиляции, если передан массив с другим количеством строк.
- Вы получаете ошибку компиляции, если передан энергонезависимый массив.
- Вы должны написать
(*ptr)
вместоptr
, что немного более многословно.
Вам нужно принять решение, хотите ли вы, чтобы компилятор выдавал ошибки в этих первых двух пунктах. Ошибок можно избежать путем приведения, но, вообще говоря, необходимость приведения - это признак того, что другой подход был бы лучше.
Если эта функция только когда-либо будет использоваться с размером3
volatile
массив, то, ИМХО, ваш текущий подход является лучшим, вызывая максимальное обнаружение ошибок компилятором.
Так как у вас есть 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
}
Это должно хорошо работать для вас:)