Home > OS >  Problem with passing a nested structure by reference to a function (Array of structures inside a str
Problem with passing a nested structure by reference to a function (Array of structures inside a str

Time:10-23

I have a problem when passing a nested structure by reference to a function. The thing is that the values of that nested structure do not change.

I have these structures defined:

struct alarm_event
{
   int1 alarm_state;
   int8 Hours;
   int8 Minutes;
   int8 Seconds;
};

struct stamp
{
   int1 record;
   int8 Hours;
   int8 Minutes;
   int8 Seconds;
};


struct sensor
{
   char  descriptor[2];              //output description
   int16 raw_value;                  //raw adc value 10bit ADC 0-1023
   int8  channel;                    //adc channel sensor wired into
   int16 alarm_limit;                          
   struct alarm_event alarm;
   struct stamp alarm_record[2];     
   int1 previous;                    
};

Inside the main, I initialize the global structure, structure sensor:

void main()
{
    struct sensor weather_station[4] =  {{"L",0,0,200,{0,0,0,0},{{0,0,0,0},{0,0,0,0}},0},
                                        {"T",0,0,300,{0,0,0,0},{{0,0,0,0},{0,0,0,0}},0},
                                        {"P",0,0,400,{0,0,0,0},{{0,0,0,0},{0,0,0,0}},0},
                                        {"H",0,0,500,{0,0,0,0},{{0,0,0,0},{0,0,0,0}},0}
                                       };
 
}

And then after reading the ADC values in a loop function (for i starting from 0 until 3), I check if the ADC value read (stored in raw_value) is greater than the alarm_limit value. In case is greater, I store the time; Hours, Minutes and Seconds into weather_station[i].alarm and call the Sample_2 function to also store these values into weather_station[i].alarm_record[j]:

         if(weather_station[i].raw_value >= weather_station[i].alarm_limit)
         {
            if(weather_station[i].alarm.alarm_state != 1)
            {
               weather_station[i].alarm.alarm_state = 1;
               weather_station[i].alarm.Hours = Hours;
               weather_station[i].alarm.Minutes = Minutes;
               weather_station[i].alarm.Seconds = Seconds;
               
               //**Upgrade
               Sample_2(&weather_station[i], i);
               
            }

The function named Sample_2 receive the address of the global structure weather_station[i] and I want that it changes the value of the paremeters record, Hours, Minutes, Seconds of weather_station[i].alarm_record[j].

void Sample_2(struct sensor *weather_station[], int i)
{
   int1 updated = 0, allones = 0;
   j = 0;
   k = 0;
   
   while(!updated)
   {  
      if( *weather_station[i].alarm_record[j].record == 0 && allones == 0 )
      {
         *weather_station[i].alarm_record[j].record = 1;
         *weather_station[i].alarm_record[j].Hours = *weather_station[i].alarm.Hours;
         *weather_station[i].alarm_record[j].Minutes = *weather_station[i].alarm.Minutes;       
         *weather_station[i].alarm_record[j].Seconds = *weather_station[i].alarm.Seconds;
         updated = 1;
      }   
      
      if(k == 1)
         *weather_station[i].previous = 0;

      if ( *weather_station[i].alarm_record[k].record == 1 && allones == 1 && *weather_station[i].previous == 0 )
      {  
         *weather_station[i].alarm_record[k].record = 1;
         *weather_station[i].alarm_record[k].Hours = *weather_station[i].alarm.Hours;
         *weather_station[i].alarm_record[k].Minutes =*weather_station[i].alarm.Minutes;
         *weather_station[i].alarm_record[k].Seconds = *weather_station[i].alarm.Seconds;
         updated = 1;
         *weather_station[i].previous = 1;
         
         if(k==1)
            *weather_station[i].previous = 0;
      }

      j  ;

      if (j > 1)
      {
         allones = 1;
      }
      
      if(j > 2)
      {
         k  ;
      }       
   } 
}

However, these values does not change. I tried to print those values after they have been modified but they do not change. For instance:

*weather_station[i].alarm_record[j].record = 1;
printf("weather_station[%u].slarm_record[%u].record = %u \n\r", i, j, *weather_station[i].alarm_record[j].record)

Since weather_station[i] in Sample_2() function is a pointer pointing to the address of weather_station[i] in main() function I think I am dereferencing the value of the structure correctly. If I try to use the another way to dereference the value of a pointer, this:

      if( weather_station[i]->alarm_record[j].record == 0 && allones == 0 )

The code does not compile and says: Previous identifier must be a pointer. Which I do not understand, because weather_station[i] is a pointer.

NOTE. This code is an attemp to use the function Sample_2() to have a modular source code. I have another file where instead of using Sample_2(), I have all the code inside the main() and it works perfectly. Therefore, the problem has to be with the pointers.

Thanks you very much in advance.

CodePudding user response:

The code you show does not compile because j = 0; and k = 0; appear in Sample_2 without j or k having been defined and because weather_station[i].alarm_record[j].record uses weather_station[i] as a struct when the weather_station parameter has been declared as an array of pointers, which would make weather_station[i] a pointer, not a struct.

Sample_2(&weather_station[i], i);

This passes the address of weather_station[i] to Sample_2. Since weather_station[i] is a struct sensor, this argument is a pointer to a struct sensor, a.k.a. struct sensor *. But then, at the definition of Sample_2, we have void Sample_2(struct sensor *weather_station[], int i). This says the parameter weather_station will be an array of pointers to struct sensor. A parameter declared as an array is automatically adjusted to be a pointer, so this results in weather_station being declared to be a pointer to a pointer to a struct sensor, a.k.a. struct sensor **.

When you compile this, the compiler should warn you that you are passing an argument of incompatible type for the parameter. However, it might not do this if you have not properly declared Sample_2 before calling it. If you have not, do so.

If you pass &weather_station[i] to Sample_2, then the corresponding parameter in Sample_2 should be delcared as a pointer to a struct sensor. It could be void Sample_2(struct sensor *weather_station, int i) rather than void Sample_2(struct sensor *weather_station[], int i).

Inside Sample_2, that struct sensor would be accessed using an expression such as weather_station->alarm_record[j].record. The -> says to use the pointer weather_station to access a struct sensor and get its alarm_record member. It is the same as (*weather_station).alarm_record[j].record. Using [i]with it as inweather_station[i].alarm_record[j].recordis wrong because the[i]was already applied in the function call;Sample_2(&weather_station[i], i);passes the address of&weather_station[i], not the address of the start of weather_station, so you do not want to apply [i]again insideSample_2`.

Additional Notes

void main()

main should be declared to return int, at least, and preferable is declared with int main(void) or int main(int argc, char *argv) unless using implementation-specific features.

The function named Sample_2 receive the address of the global structure weather_station[i]

(a) weather_station is not global. It is declared inside main, which makes the name have block scope, not global scope, and the object it names has automatic storage duration.

(b) Do not use bold for names from source code or other things from source code. Use the code style, which can be marked with the <code> tag or the ` character, as in <code>…</code> or `…`

  •  Tags:  
  • c
  • Related