Array of Structs not compiling

Greetings;

After helping me with accessing struct elements with a for loop - Programming Questions - Arduino Forum,
(indexing structs), I'm stick again, trying to build and initialize an array of said struct.

This blip is before the loop

// analog sensor setup
struct PSensor {
int pId = 5;         //identifies Analog Channel (min channel 5)------not in PRESSURE
int pSamples = 1;    //number of samples to filter reading (default 1)
int pCalZero = 20;    //sensor reading with no water column
int pCalHigh = 30;    //sensor reading with max water column
int hRefZero = 40;    //actual NO watercolumn height of sensor in CM (default is 0)
int hRefHigh = 200;    //actual HIGH watercolumn height in CM (default 200)
int unitAdjust = 60;  // adjust units to display VOLUME on screen (default 0-> bars, 1->CM, other m3))
int maxVol = 70;    // maxVolume of tank (default 0)
};
//int testSensor[8] = {pId, pSamples, pCalZero, pCalHigh, hRefZero, hRefHigh, unitAdjust, maxVol};

PSensor aDisplay;
int *aPointer = (int*)&aDisplay;

int rainTank = 8;    //rain water tank sensor shows volume of water
int houseLine = 9; //pressure inside the house
int poolFilter = 10;    //pressure at the pool filter input
int balanceTank = 11;   //pool balance tank volume

PSensor pChannel[4] = {
  {rainTank,1,2,3,4,5,6,7},
  {houseLine,10,2,3,4,5,6,7},
  {poolFilter,11,2,3,4,5,6,7},
  {balanceTank,12,2,3,4,5,6,7}
};

When I compile it, I get the following error:

could not convert '{8, 1, 2, 3, 4, 5, 6, 7}' from '<brace-enclosed initializer list>' to 'PSensor'

I tried moving the array definition into setup(), but it produces the same error.

I think I'm implementing verbatim what nickgammon says in #6 of "Array of Structs", but apparently not...

You are missing the typedef to define the structure layout....

typedef struct {
.....
} PSensor;

This should just define the types and names of the fields, no initializing with values.

Only once you’ve do that can you create instances of it....

PSensor aDisplay;

Or

PSensor pChannel[4] = {
....
};

Apparently you can't initialize a struct if any of the members have a default initializer. This copiles without error or warning:

// analog sensor setup
struct PSensor
{
  int pId;         //identifies Analog Channel (min channel 5)------not in PRESSURE
  int pSamples;    //number of samples to filter reading (default 1)
  int pCalZero;    //sensor reading with no water column
  int pCalHigh;    //sensor reading with max water column
  int hRefZero;    //actual NO watercolumn height of sensor in CM (default is 0)
  int hRefHigh;    //actual HIGH watercolumn height in CM (default 200)
  int unitAdjust;  // adjust units to display VOLUME on screen (default 0-> bars, 1->CM, other m3))
  int maxVol;    // maxVolume of tank (default 0)
};


int rainTank = 8;    //rain water tank sensor shows volume of water
int houseLine = 9; //pressure inside the house
int poolFilter = 10;    //pressure at the pool filter input
int balanceTank = 11;   //pool balance tank volume


struct PSensor pChannel[4] =
{
  {rainTank, 1, 2, 3, 4, 5, 6, 7},
  {houseLine, 11, 2, 3, 4, 5, 6, 7},
  {poolFilter, 12, 2, 3, 4, 5, 6, 7},
  {balanceTank, 13, 2, 3, 4, 5, 6, 7}
};


void setup() {}
void loop() {}

The 'typedef' is not longer needed. Declaring a struct that way is automatically a typedef.

Please do not use a integer pointer to that struct. Even if the struct contains integers, you should not use a integer pointer to point inside that struct. That is bound to go wrong.

When making a struct called 'PSensor', you create a new type of variable. It will be like 'int' or 'float' or 'long', but now it is called 'PSensor'.
During the definition of that new type, it is not allowed to fill it with default values, because there is nothing to fill. It is not a variable, only a type.

Once you make a variable of that type, then that variable has a memory location and you can initialize it with values.

struct PSensor {
int pId;         //identifies Analog Channel (min channel 5)------not in PRESSURE
int pSamples;    //number of samples to filter reading (default 1)
int pCalZero;    //sensor reading with no water column
int pCalHigh;    //sensor reading with max water column
int hRefZero;    //actual NO watercolumn height of sensor in CM (default is 0)
int hRefHigh;    //actual HIGH watercolumn height in CM (default 200)
int unitAdjust;  // adjust units to display VOLUME on screen (default 0-> bars, 1->CM, other m3))
int maxVol;    // maxVolume of tank (default 0)
};

const int rainTank = 8;    //rain water tank sensor shows volume of water
const int houseLine = 9; //pressure inside the house
const int poolFilter = 10;    //pressure at the pool filter input
const int balanceTank = 11;   //pool balance tank volume

PSensor pChannel[4] = 
{ 
  { rainTank, 1,2,3,4,5,6,7 },
  { houseLine,  10,2,3,4,5,6,7},
  { poolFilter, 11,2,3,4,5,6,7},
  { balanceTank, 12,2,3,4,5,6,7},
};


void setup() {}
void loop() {}

johnwasser has made the same sketch as me ! I'm going to post it anyway because I have a little more explanation. It is allowed in c++ to use 'PSensor' as a type without 'struct' in front of it when creating 'pChannel'.

his code compiled on my laptop with gcc.

i came to the same conclusion that you can't specify an initial value for struct member using the Arduino IDE.

gcc allows designated initializers for a typedef. But I can't get wrap my head around that :o

To All,

Thanks for the enlightenment!

here's some working code:

// analog sensor setup
struct PSensor {
int pId; //identifies Analog Channel (min channel 5)------not in PRESSURE
int pSamples; //number of samples to filter reading (default 1)
int pCalZero; //sensor reading with no water column
int pCalHigh; //sensor reading with max water column
int hRefZero; //actual NO watercolumn height of sensor in CM (default is 0)
int hRefHigh; //actual HIGH watercolumn height in CM (default 200)
int unitAdjust; // adjust units to display VOLUME on screen (default 0-> bars, 1->CM, other m3))
int maxVol; // maxVolume of tank (default 0)
};

int rainTank = 8;    //rain water tank sensor shows volume of water
int houseLine = 9; //pressure inside the house
int poolFilter = 10;    //pressure at the pool filter input
int balanceTank = 11;   //pool balance tank volume
#define NUM_CHANNEL 4
PSensor pChannel[NUM_CHANNEL] = {
  {rainTank,1,2,3,4,5,6,7},
  {houseLine,10,2,3,4,5,6,7},
  {poolFilter,11,2,3,4,5,6,7},
  {balanceTank,12,2,3,4,5,6,7}
};

int *aPointer = (int*)&pChannel;
uint8_t pLength = sizeof(pChannel)/sizeof(int)/NUM_CHANNEL;



//------------------------------SETUP------------------
void setup() {                      // startup function
  //Set up Screen
  Serial.begin(115200);
  Serial.flush();
  Serial.println(F("Menu Test"));

  
    for (uint8_t id = 0; id < 4; id++) {
      Serial.print(pChannel[id].pId);
      Serial.print(":");
    for (uint8_t field = 1; field < 8; field++) {
      Serial.print(aPointer[(pLength*id)+field]);
      Serial.print(",");
    }
    Serial.println();
  } //eof drawing buttons

void loop() {}

@Koepel, about your comment inre using ints for pointers: sterretje taught me that one, using sizeof()s, in //forum.arduino.cc/index.php?topic=687420.msg4623090#msg4623090, post #6.

I added that to the loop for clarity and portability. It seems to work.

14:18:26.355 -> Menu Test
14:18:26.355 -> 8:1,2,3,4,5,6,7,
14:18:26.355 -> 9:10,2,3,4,5,6,7,
14:18:26.355 -> 10:11,2,3,4,5,6,7,
14:18:26.355 -> 11:12,2,3,4,5,6,7,

This matches the values of each element of each array in the setup.

Cheers!!