UB_Roy
UB_Roy

Reputation: 691

Passing Pointer to an Array of structures

This is for MPLABXC8 compiler I have researched and found number of topics related. But not able to solve my issue. 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];

Now my variable

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

Now I am passing pointer to my function

GetOperationSeqForTransportReq(1,1,&CurOperPlan);

below is the function

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

only the 0th element is accessable. Also compiler complaints that structure pointer passed to structure array pointer. I tried by incrimenting the pointer in function. It seems incrimenting the whole Array pointer. It seems to me that &CurOperPlan is adress pointer to 0th index structure only. The whole array is not contained it. please help.

Upvotes: 1

Views: 980

Answers (3)

M.M
M.M

Reputation: 141648

Inside the function, you need:

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

This is because CurTransportPlan is a pointer to your array. So you must dereference it to get the array. Then you can apply array indexing to the array.

Link to working example


To explain why the first one seemed to work, we can rewrite the code applying the equivalence transformations X->Y = (*X).Y, and X[N] = *(X+N).

The correct indexing in array notation should be CurTransportPlan[0][0].DevID1 and CurTransportPlan[0][1].DevID1 ; however your code swapped the indices in both cases. This meant the first one still worked but the second one broke.


Regarding your code design: it's been noted that there are two ways to approach passing an array to a function:

  1. You can pass a pointer to the first element of the array, as alk suggests (passing the length separately, or hard-coding it)

  2. You can pass a pointer to the entire array as you are currently doing.

I will list some of the differences between these two designs. Using your design, i.e. the pointer-to-whole-array:

  • You get a compilation error if an array with a different number of rows is passed.
  • You get a compilation error if a non-volatile array is passed.
  • You must write (*ptr) instead of ptr, which is slightly more verbose.

The decision for you to make is whether you want the compiler to give errors in those first two points. The errors can be avoided by casting, but generally speaking, need to cast is a sign that the other approach would have been a better design.

If this function is only ever to be used with the size-3 volatile array then IMHO your current approach is the best one, invoking maximum compiler detection of errors.

Upvotes: 1

alk
alk

Reputation: 70981

Change this

GetOperationSeqForTransportReq(1,1,&CurOperPlan);

to be

GetOperationSeqForTransportReq(1, 1, CurOperPlan);

and this

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

to be this

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

For completeness also change this

OneStageOpType CurOperPlan={0};

to be

OneStageOpType CurOperPlan = {{0}};

Upvotes: 3

no one special
no one special

Reputation: 1762

As you have a typedef of three elements array:

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

The problem looks to be:

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

In above function you are declaring parameter as a pointer to 3-element array, but you should pass it as a pointer to first element of array. This means you should do the following instead:

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      
}

This should works fine for you :)

Upvotes: -1

Related Questions