JohnMerlino
JohnMerlino

Reputation: 3928

pointer to many structures in c

I can have many sensors. Each sensor has an address, current and pressure. Due to the fact I don't know how many sensors there could be, I thought of creating a pointer to structs:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct sensor {
  unsigned long long int           address;
  float                            current;
  unsigned char                    pressure_units;
};

static struct sensor *sensors;

struct sensor *createSensor(unsigned long long int address, float current, unsigned char pressure_units)
{
  struct sensor *temp = malloc(sizeof(struct sensor));
  // (*temp).address
  temp->address = address;
  temp->current = current;
  temp->pressure_units = pressure_units;
  return temp;
}

void checkSerialHart(int sensorId)
{
    sensors = createSensor(10000*sensorId,sensorId+3.0,sensorId);
}

int main(int argc, char *argv[])
{
    int i, j;
    for(i=0,j=0;i<3;i++)
    {
        // test case where sensor n doesn't respond
        if(i != 1)
        {
            checkSerialHart(j);
            ++j;
            ++sensors;
        }
    }
    printf("address: %llu current: %f pressure: %c\n", sensors[0].address, sensors[0].current, sensors[0].pressure_units);
    printf("address: %llu current: %f pressure: %c\n", sensors[1].address, sensors[1].current, sensors[1].pressure_units);
}

I am having trouble keeping a pointer to structs where I can move through the pointer to get values of different sensors. The above prints this:

address: 580340276002816 current: 0.000000 pressure: 
address: 0 current: 0.000000 pressure: 

But I expected this:

address:0,current:3.000000,pressure_units:0
address:20000,current:5.000000,pressure_units:2

What may I be doing wrong?

Upvotes: 0

Views: 84

Answers (3)

Lee Duhem
Lee Duhem

Reputation: 15121

Your checkSerialHart() will overwrite sensors every time you call it.

Here is one way (not the best) to achieve your goal:

static struct sensor **sensors;
static int sensors_count = 0;

...

void checkSerialHart(int sensorId)
{
    sensors = realloc(sensors, (sensors_count+1)*sizeof(*sensors));
    if (sensors == NULL)
        exit(EXIT_FAILURE);
    sensors[sensors_count] = createSensor(10000*sensorId,sensorId+3.0,sensorId);
    sensors_count++;
}

...

for(i=0,j=0;i<3;i++)
{
    // test case where sensor n doesn't respond
    if(i != 1)
    {
        checkSerialHart(j);
        ++j;
    }
}

for (i = 0; i < sensors_count; i++)
    printf("address: %llu current: %f pressure: %c\n",
        sensors[i]->address, sensors[i]->current, sensors[i]->pressure_units);

Upvotes: 2

M.M
M.M

Reputation: 141554

Currently, your

static struct sensor *sensors;

points to a single sensor. When you increment it, you no longer point at a valid sensor, causing undefined behaviour when you later deference.

You have to choose between one of two fundamentally different designs:

  1. An array of sensors
  2. An array of pointers to sensor

(As I write, the other solution mixes up these two options, it won't work as posted).

If you go with option (2) then the only modification you need to make is:

static struct sensor *sensors[MAX_SENSORS];
static size_t num_sensors = 0;

Then you can do sensors[num_sensors++] = createSensor(....

You should avoid doing ++sensors, and instead either use an index or another pointer if you want to iterate over the sensors. You could also dynamically allocate sensors instead of having a fixed maximum.

For option (1) you would need to re-design the createSensor function. It can no longer return a pointer to a new Sensor, nor malloc memory for a single sensor. Instead, you have to increase the size of your dynamically-allocated sensor array, and then create the new sensor in the space you just allocated.

In either case I would suggest having separate functions for "growing" your allocated storage, than for initializing a new sensor. That will help keep your code clear and easy to maintain.

Upvotes: 0

Mantosh Kumar
Mantosh Kumar

Reputation: 5731

Your following line is causing the problem:

++sensors;

"sensors" is the global static variable which should be store the base pointer of your array. But inside your for loop, it gets incremented and starts pointing to next(some memory). Hence while printing, it does starts pointing to base address which you wanted to achieve from this program.

Upvotes: 1

Related Questions