typedef struct problem

This is probably a simple error, but I cannot see it.

Programming an IR receive function for the NEC remote. This code is NOT complete or tested, just trying to get a clean compile…

When I compile this in the Arduino IDE I get errors
NEC_IR_receive:58: error: expected constructor, destructor, or type conversion before ‘.’ token
NEC_IR_receive:59: error: expected constructor, destructor, or type conversion before ‘.’ token
NEC_IR_receive:61: error: expected unqualified-id before ‘for’

Line 58 is irSharedData.pin = IR_INPUT_PIN; // initialise the needed structure values, not all need initialising

I cannot see why this is happening, OK my C is rusty, but still can’t see it!

Any Ideas??

NEC_IR_receive.ino (11 KB)

SOLVED: was trying to initalise the structure values too early - moved to setup and compiles fine, Code cannot be executed before setup is reached!

Putting your typedefs in a separate .h files saves you a lot of trouble

Haven't tried it but I don't think it would make any difference in this case.. Include just tells the compiler to pause reading the main file and process the include file first, then resume. The error came from the initialization of the instance of the structure outside of setup or loop.
Probably initialisation by = {values....} would work but again haven't tried it.

You'll appreciate nilton61's tip if you ever need to use non-built-in types in function signatures. Although it shouldn't be necessary, it is the preferred way to work around a bug in the Arduino IDE which causes it to screw up your code in this situation.

Just make the struct a real struct, the typedef does nothing useful here ( C++, not C )

This code isn’t in a function:

irSharedData.pin = IR_INPUT_PIN;	// initialise the needed structure values, not all need initialising
irSharedData.state = IRSTATE_WAITING;

for(int i = 0; i < sizeof(irSharedData.signals); i++)	// don't really need to do this but will make any debugging easier
  irSharedData.signals[i] = 0;	
irSharedData.signalIndex = 0;
irSharedData.errorCode = IRERR_NOERROR;
irSharedData.pin = IR_INPUT_PIN;	// initialise the needed structure values, not all need initialising
irSharedData.state = IRSTATE_WAITING;

.

Use headers like everyone has pointed out.

Thank you for all the advice, and I do use header files, but during the design/development of a small piece of code I normally don't use headers, it's easier and more flexible. This once working as a proof of concept will be converted to a library.

However the error I identified is the actual code is not expected, it's not in a function in this case setup is appropriate until converted to a library.

I would not expect copying it into a header file and including it would change anything, please let me know if I am wrong.

As to the use of typedef, it has been around in C, long before C++ was thought of. I tend to use typedef as then the struct definition is in the header file where it belongs and the memory allocation in the code, where it belongs. Also allows multiple definitions of the same struct. which can be useful. I agree that in the code given it has no effect. If there is an Arduino problem with typedef, again please let me know.

PeterH - thank you for the heads up with the IDE bug. Is there any resource where the IDE bugs and workarounds are listed?

This seems a very useful forum, thank you all for your time and help.

GrahamB:
If there is an Arduino problem with typedef, again please let me know.

The code is compiled with a standard C++ GCC compiler so the behaviour of structs are as defined in C++. This means that the typedef is redundant since the struct is implicitly also a type.

Pardon my ignorance, I first learnt C in 1987, by the time C++ came round I was no longer a programmer but an architect, so while I understand C++ have never used it in anger. Arudino experience about 3 weeks.

Wouldn't missing off the typedef actually instantiate a structure?

GrahamB:
Wouldn't missing off the typedef actually instantiate a structure?

No. Just declare a struct, and as well as the struct you also get a type of the same name, just as if you have typedefed it. I understand it was introduced to enable the language designers to bridge the gap between classes and structs but whatever the reason - the type is now defined implicitly.

If there is an Arduino problem with typedef, again please let me know.

The arduino IDE generates function prototypes for you, and puts them "near" the top of your source. However, it doesn't do a particularly good job of figuring out the best place to put the prototypes. And it generates the prototypes even if you write your own.
So if you have:

typedef struct foo { blah, blah } foo_t;
void setup() {}
void loop() {
   foo_t mystruct;
   my_function(&mystruct);
}
void my_function(foo_t * ms) {
  // blah blah
}

The IDE will generate a .cpp file that looks like:

void my_function (foo_t *ms);  //generated
typedef struct foo { blah, blah } foo_t;
void setup() {}
   :

the prototype referencing foo_t comes before foo_t is defined, and you get an error.
The IDE is smart enough to put the prototypes AFTER any initial set of preprocessor statements, so if you had defined foo_t in foo.h and included it, you would have gotten the following, which would work fine.

#include "foo.h"
void my_function (foo_t *ms);  // generated
void setup() {}
   :

(The other famous problem that this causes is with conditional compilation. The prototypes can get inserted in the middle of a conditional that isn't evaluated)

I've read comments suggesting that in some recent version of the IDE the auto-generated prototypes are only inserted if they are missing. If true, putting your own prototypes in the right place would be a better workaround. (I still use 1.0.4 and it doesn't work in that version.)

I've also read comments suggesting that some version of the IDE has / will in future have the option to disable the auto-prototype generating feature. Or perhaps I just dreamed that. Since the feature was misguided and poorly implemented, IMO the sooner it is got rid of the better.

I’ve used my own prototypes since 0021, never had a problem of duplicate prototypes.

Remember the signature must match exactly:

Pretend sketch:

void Foo(){
 Serial.print( "HI" ); 
}

void setup() {
  Foo();
}

void loop() { }

Adding the prototype:

void Foo();

produces:

#line 1 "BareMinimum.ino"

#include "Arduino.h"
void setup();
void loop();
#line 2
void Foo();

void Foo(){
 Serial.print( "HI" ); 
}

void setup() {
  Foo();
}

void loop() { }

If I add the same prototype ( but not a textual match )

void  Foo (); //Two spaces instead of one.

this produces:

#line 1 "BareMinimum.ino"

#include "Arduino.h"
void Foo();
void setup();
void loop();
#line 2
void  Foo ();

void Foo(){
 Serial.print( "HI" ); 
}

void setup() {
  Foo();
}

void loop() { }

The multiple definitions are fine unless using a struct, as the object is still not seen before use.
However like I said I have had no problem with duplicate prototypes appearing and breaking structs.
I have used 0021 to 1.0.5 and tested 1.5.2.

Download my test sketch and try it. If it works, there is no duplicates.

auto_proto_fail.ino (169 Bytes)