Problems understanding Struct in this example !

Hi,

Link RF24Network: Network Layer for RF24 Radios

I am trying to understand how struct works in this example found below. I have tried to find out using the internet but find the explanations very confusing.My questions relate to the lines marked with (1) (2) (3) respectively.

This is what I think may be happening ?

(1) Assigns members unsigned long ms; unsigned long counter;, but they are not put into memory or take any space.

(2) payload seems to become a variable here ? also millis(), packets_sent are used here but how are they related to (1)

(3) What does &payload do ?

It seems unsigned long ms; unsigned long counter; are never used ?

i would welcome a clear and easy to understand reply as I have never used structs before.

Thanks

Regards Gary

/*
 Copyright (C) 2012 James Coliz, Jr. <maniacbug@ymail.com>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 version 2 as published by the Free Software Foundation.
 */

/**
 * Simplest possible example of using RF24Network 
 *
 * TRANSMITTER NODE
 * Every 2 seconds, send a payload to the receiver node.
 */

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

// nRF24L01(+) radio attached using Getting Started board 
RF24 radio(9,10);

// Network uses that radio
RF24Network network(radio);

// Address of our node
const uint16_t this_node = 1;

// Address of the other node
const uint16_t other_node = 0;

// How often to send 'hello world to the other unit
const unsigned long interval = 2000; //ms

// When did we last send?
unsigned long last_sent;

// How many have we sent already
unsigned long packets_sent;

// Structure of our payload
struct payload_t                              // (1)
{
  unsigned long ms;
  unsigned long counter;
};

void setup(void)
{
  Serial.begin(57600);
  Serial.println("RF24Network/examples/helloworld_tx/");
 
  SPI.begin();
  radio.begin();
  network.begin(/*channel*/ 90, /*node address*/ this_node);
}

void loop(void)
{
  // Pump the network regularly
  network.update();

  // If it's time to send a message, send it!
  unsigned long now = millis();
  if ( now - last_sent >= interval  )
  {
    last_sent = now;

    Serial.print("Sending...");
    payload_t   payload = { millis(), packets_sent++ };                                // (2)
    RF24NetworkHeader header(/*to node*/ other_node);
    bool ok = network.write(header,&payload,sizeof(payload));                   // (3)
    if (ok)
      Serial.println("ok.");
    else
      Serial.println("failed.");
  }
}
// vim:ai:cin:sts=2 sw=2 ft=cpp
  1. define a structure (a template if you like)
  2. make an instance of the structure and put some values in it.
  3. take the address of the structure.

That is some weird programming, but after a while it does make sense.

This declares a template.

struct payload_t
{
  unsigned long ms;
  unsigned long counter;
};

So beside 'int', 'float' and 'long', you can now also declare something that is called 'payload_t'.

And such a variable is created:

  payload_t   payload = { millis(), packets_sent++ };

A variable of the type 'payload_t' is created. That variable is a structure with two long variables, 'ms' and 'counter'.
The 'ms' and 'counter' are filled upon the creation of the variable.

Those elements can be filled in a normal way:

  // same code as this:
  //       payload_t   payload = { millis(), packets_sent++ }; 
  payload_t   payload;    // create a structure.
  payload.ms = millis();
  payload.counter = packets_sent++;

The whole structure is transmitted.

bool ok = network.write(header,&payload,sizeof(payload));

Why all this trouble ? because the receiver probably needs a data package with 'ms' and 'count', so it would be nice to create a structure for that data package. The only weird thing is how that structure is filled upon creation.

That is some weird programming

I'm not sure why you say that.

Hi,

Thanks for that info AWOL. its starting to make some sense.

  1. define a structure (a template if you like) ... does this reserve a space in memory for the ms and counter ?

  2. make an instance of the structure and put some values in it. ... put the values in above, do they have to be in order, 'ms' and 'millis' are both the first item in each case and so on.

  3. take the address of the structure. Go to this address find its length and and send all data out.

regards

Gary

Nothing weird
http://www.cplusplus.com/doc/tutorial/structures/

  1. No, it does not reserve space until you create an instance of that structure - this is just a template.
  2. The initialisers are in the same order as the labels are in the structure definition unless they are qualified with the dot operator.
  3. There is no "goto" implied - all that is happening is that the address of the structure is being taken, so that the address (aka pointer) is passed into the function, not the structure itself.

The problem there is that you have no typedef name for your struct.

michinyon:
The problem there is that you have no typedef name for your struct.

Why is that a problem?

michinyon:
The problem there is that you have no typedef name for your struct.

C++ automagically creates one for you. Typedef, with structs, is now obsolete.

Typedef, with structs, is now obsolete.

Apple Objective -C still use this approach XD

HugoPT:

Typedef, with structs, is now obsolete.

Apple Objective -C still use this approach XD

Apple Objective-C is not C++. It's about as close to C++ as an orange is to the Suez crisis.

Typedef, with structs, is now obsolete.

Unless you like clarity. I don't like code that automagically does stuff to me. I mean for me.

PaulS:

Typedef, with structs, is now obsolete.

Unless you like clarity. I don't like code that automagically does stuff to me. I mean for me.

I'm with you on that one :wink:

Personally I never really used typedef anyway, and preferred to explicitly say it was a struct I was working with. I still do, even with automatic typedefs. I like to know that the variable I am working with is a structure or other similar compound object (unless it's a class, of course).

Personally I never really used typedef anyway, and preferred to explicitly say it was a struct I was working with. I still do, even with automatic typedefs.

I use lower case first letters for all variables except structs and lists. So, I use something like

struct zoneData
{
   // stuff
};

and then a typedef statement:

typedef struct zoneData ZoneData;

Then, when I see ZoneData in my code, i know that it is a either a struct or a list. Since I use plural names for lists, and ZoneData is not a plural, it's pretty easy for me to remember, then, that ZoneData refers to a struct (and that pZoneData is a pointer to an instance of that struct).