2016-03-26 3 views
1

Это для компилятора MPLABXC8 Я исследовал и нашел несколько связанных тем. Но не смог решить мою проблему. Моего массив ЬурейеГоПередача указателя на массив структур

 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

Автор: _not_ typedeffing массивов. –

+0

Помните, что сам массив является указателем. Вы разыскиваете указатель (массив) здесь: 'GetOperationSeqForTransportReq (1,1, & CurOperPlan);' либо использовать 'GetOperationSeqForTransportReq (1,1, CurOperPlan);' или '(* CurTransportPlan) [0] -> DevID1 = 5; 'с типом' OneStageOpTag * '. – Myst

+1

Как заметил @ ThomasPadron-McCarthy - ваш код ошибся, когда вы набрали массив. – Myst

ответ

-1

Как вы уже ЬурейиЙ из трех элементов массива:

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  
} 

Это должно отлично работает для вас :)

+0

Спасибо. Он работает, но с небольшим разнообразием. , так как «CurTransportPlan» теперь является указателем на элемент, [0] или [1] невозможен. CurTransportPlan-> DevID1 = 5; // это работает, а затем Incriment указатель CurTransportPlan ++; CurTransportPlan-> DevID1 = 6; // теперь это изменяет элемент [1]. В этом случае в качестве отдельных элементов доступен единственный массив. Спасибо за помощь – user2454516

+0

Неверный перевод '& CurOperPlan', поскольку он вычисляет указатель на массив, но то, что вы хотите, является указателем на его первый элемент, поэтому просто передайте' CurOperPlan'. Компилятор должен предупредить об этом. Любые способы, по которым код может работать, поскольку значение адреса массива всегда совпадает с значением адреса первого элемента массива ... – alk

+0

Передача указателя на элемент, а затем включение этого указателя для получения другого два элемента, похоже, работают нормально. CurOperPlan или & CurOperPlan не имеет практического значения при использовании элемента. Ну, это похоже. Но в любом случае, когда я пропускаю CurOperPlan или & CurOperPlan, индексирование недоступно в функции назначения. Спасибо – user2454516

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}}; 
+0

'{0}' - правильная идиома для нулевого инициализации агрегата во всех случаях. ИМХО, придерживающееся общих идиом, - неплохая идея. Были некоторые более ранние версии gcc, которые предупреждали о неполной привязке к '{0}', но я считаю, что они были обновлены сейчас, чтобы не дать этого фиктивного предупреждения. –

+0

@ M.M: «* они были обновлены сейчас, чтобы не дать этого фиктивного предупреждения *« Действительно? Большой! :-) Я, возможно, должен обновить хотя ...:} – alk

1

Внутри функции, вам необходимо:

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

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

Link to working example


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

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


Что касается вашего дизайна кода: это было отмечено, что существует два способа подхода передачи массива в функцию:

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

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

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

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

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

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

+0

Согласен, однако я не думаю, что OP намеревался реализовать эту дополнительную косвенность. – alk

+0

@alk обновленный ответ включить обсуждение –

+0

Nice :-) - можно добавить, что для 2-й конструкции также можно изменить значение, передаваемое «по ссылке» внутри функции. – alk

Смежные вопросы