Hi,
Having some issues here getting a typedef struct to work. I have been searching for an answer to this for waaay too many hours.
I have two sketches in my project and one shared header. When I put a typedef struct or typedef enum I get the following: In file included from a.pde:1: a.h:1: error: redefinition of 'struct aStruct' a.h:1: error: previous definition of 'struct aStruct' a.h:4: error: invalid type in declaration before ';' token a.h:4: error: conflicting declaration 'typedef int aStruct' a.h:4: error: 'aStruct' has a previous declaration as 'typedef struct aStruct aStruct' a.h:9: error: conflicting declaration 'typedef struct bStruct bStruct' a.h:9: error: 'bStruct' has a previous declaration as 'typedef struct bStruct bStruct'
Thanks in advance for your help - I appreciate it!
The code is reproduce this ridiculously simple: main sketch:
#include "a.h"
void setup()
{
}
void loop()
{
}
Header file a.h
typedef struct aStruct {
int a;
int b;
} aStruct;
typedef struct {
int a;
int b;
} bStruct;
Are these two tabs of the same project? If so, the IDE joins them together into one single file before compiling, so you are effectively including your header twice.
Tip: Always wrap your headers in single-inclusion structures:
#ifndef _MY_HEADER_H
#define _MY_HEADER_H
// Header code here
#endif
That way, if the header is included twice, or gets included by another header, the second (and subsequent) inclusions will be ignored.
HI,
Yes they are - I attached the whole sketch to the post. I have one project with two pde files.
I just tried it out and it resolved the issue
This is the first time I have split my code into multiple modules so I have not experienced this quirk before. If I understand you right then I only include them once.
If they are concatenated then does that mean that all header contents become global to all modules?
Thanks
Bryon
bryonb:
HI,
Yes they are - I attached the whole sketch to the post. I have one project with two pde files.
I just tried it out and it resolved the issue
This is the first time I have split my code into multiple modules so I have not experienced this quirk before. If I understand you right then I only include them once.
If they are concatenated then does that mean that all header contents become global to all modules?
Thanks
Bryon
Yep. It's done so that you don't have to declare any of your functions / variables as external in order to reference them properly. Makes for lazy programmers, but also means that new programmers don't have to know about sharing variables and functions between C++ files. It does have little trip-ups though
Thanks Paul. I tried your suggestion and the same error occurs. If they are concatenated then I can't see how that would work actually.
Either way, I have a solution and I am now painfully aware that it is not straight forward to port from a full C compiler to Arduino.
Thanks to all for helping resolve this for me. The responses are faster than a paid-for vendor-support contract!
Bryon
Why not just dispense with the typedef altogether? It's not necessary and only blurs the fact that you are using a structure for the sole benefit of not having to say struct xxxx yyyy when you want to create one.
Can you do that? Most of the code I've seen/written has done
typedef struct aStruct_ {
int a;
int b;
} aStruct;
to explicitly separate the structure name from the type name. But I'm not sure whether that was mostly a style thing, or an actual namespace requirement. (It's an easy and painless fix...)
defines a structure called "struct fred" and you can declare an instance of this struct by
struct fred fred_instance ;
or by
struct fred
{ int a;
int b;
} fred_instance ;
On the other hand
typdef struct fred
{ int a;
int b;
} another_name_for_fred
defines a struct which has two alternative names, "struct fred" and "another_name_for_fred". So you can declare instances by
struct fred instance_a;
another_name_for_fred instance_b ;
and instance_a and instance_b should be functionally equivalent.
It's confusing.
So what you have done in your example, is used the same identifier for the struct and also for it's typedef alternative name, which is probably confusing. If you want to give something an alternative name, it should probably be a different alternative name. If you were called John, and you said your alternative name was John, well that would be silly.
Or, don't typedef at all, as (I believe, correct me if I am wrong) C++ does an implicit typedef of all structs anyway.
Of course, we have allowed ourselves to get sidetracked and off topic. This issue wasn't the typedefs themselves, but the fact that the OP had two tabs, and was including the same header file in both, which resulted in a single cpp file with the header included twice when the IDE concatenated the two tabs into one file before attempting to compile.
Now if I looked at your last example there, I would have trouble to figure out if 'foobar' was a typedef name
for that struct, or an instance of it.
I hate writing things which, when I look at it six months later, I can't figure out what it is, so I try
to avoid writing things like that in the first place.
afremont is on the money, drop the typedef. michinyon shows the main reason why the added confusion is not worth it; by dropping the typedef, your aliased type name suddenly becomes a variable.
aliased structs are only useful in C++ when you actually need something different to what is written before the '{}', such as anonymous structs, i.e
typedef struct{
int a;
int b;
} fred, *fredptr;
//Allows aliased names:
fred a;
fredptr b = &a;
Yes 'struct' is legal on variable definitions, however it is only needed to disambiguate names:
int fred( int a ){ //Function named 'fred'
return ~a;
}
struct fred //structure named 'fred'
{ int a;
int b;
};
struct fred a; //Struct required to disambiguate 'fred'