View previous topic :: View next topic |
Author |
Message |
jeremiah
Joined: 20 Jul 2010 Posts: 1362
|
variable type forward declaration [solved] |
Posted: Fri Apr 11, 2014 12:41 pm |
|
|
Versions: 5.019 & 5.024...suspect more. PIC doesn't really matter.
I was trying to figure out how to forward declare a variable type in CCS. In most C compilers, I can do the following:
Code: |
#include <18F4520.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT
#use delay(clock=20000000)
struct nodeA; //comment this out and it compiles
struct nodeA{
int16 v;
};
void main (void){
struct nodeA n;
n.v= 0;
while(TRUE);
}
|
but as my comment suggests, the forward declaration doesn't compile. Am I forgetting something simple? If not, is there an alternative in the CCS compiler? I'll be honest and say I am not as familiar with older versions of C, so maybe it is not supported, but I wanted to check.
I know the example is a bit non-sensical since there is no need for the forward declaration, but I wanted to have some structures that cross reference each other and this was a simple example I could produce of the error.
Last edited by jeremiah on Sat Apr 12, 2014 2:32 pm; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19619
|
|
Posted: Fri Apr 11, 2014 2:20 pm |
|
|
Original C, does not allow forward declaration of variables.
A form was added in about C98 (don't quote me on the version...), but required the first declaration to use 'void', rather than an explicit type. So you declare as:
Code: |
#include <18F4520.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT
#use delay(clock=20000000)
extern void nodeA; //forward declaration
struct nodeA
{ //This then overrides it for the local context.
int16 v;
};
void main (void)
{
struct nodeA n;
n.v= 0;
while(TRUE);
}
|
Then later, a form like you show was added (C99?).
The 'extern' void trick basically relies on an external variable always being 'overidden', if a local declaration is then made.
CCS appears to accept the slightly older form, but not the incomplete structure declaration. May do what you need?.
Best Wishes |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1362
|
|
Posted: Fri Apr 11, 2014 5:32 pm |
|
|
Thanks! I'll try it out in my more complex program and see how it goes (should be pretty straight forward). The only way I was able to work around it was using void pointers and casting, but this would work much smoother.
I was guessing it wasn't allowed, but didn't have any older compilers to test out on.
Edit: no good. I appears it thinks I am defining a function with the extern. It errors expecting a parenthesis. If I toss struct in front it errors looking for braces.
Code: |
#include <18F4520.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT
#use delay(clock=20000000)
extern void nodeA; //forward declaration
struct nodeB{
struct nodeA *p; //doesn't compile
nodeA *p; //doesn't compile
int16 v;
};
struct nodeA{
int16 v;
};
void main (void){
struct nodeA n;
n.v= 0;
while(TRUE);
}
|
I might be out of luck with this. Any other ideas? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19619
|
|
Posted: Sat Apr 12, 2014 4:33 am |
|
|
OK.
What you want to do, is not generally supported in C. It is in C's that have C++ variants. You have what is known as an 'incomplete type' (basically the compiler doesn't know the size of it), and these can't be used in structure declarations.
Quote from a current C manual...
"Struct type declared by a forward declaration (i.e. an incomplete type) can be used only in a limited number of ways. You can't use incomplete types in object definitions and you cannot access data fields of incomplete struct types."
I suspect the compilers you are trying are ones that at least in part support C++ operations (that do allow this). |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1362
|
|
Posted: Sat Apr 12, 2014 7:26 am |
|
|
Yeah, GCC and VStudio are the ones I have used in the past.
A question:
Ttelmah wrote: |
Quote from a current C manual...
"Struct type declared by a forward declaration (i.e. an incomplete type) can be used only in a limited number of ways. You can't use incomplete types in object definitions and you cannot access data fields of incomplete struct types."
|
While I understand that, I would have suspected declaring a pointer to an incomplete type would be fine since you aren't referencing size or elements of it to do that. Doing so would fit the manual excerpt you provided. Using a pointer of an incomplete type in another type declaration doesn't violate the "object definition" or "access data fields" parts that it highlights. I know I couldn't simply define an object of it because the compiler would have to know how to construct the object, but the compiler doesn't need to know how to construct the object from a pointer until you dereference the pointer.
In short, assuming I could forward declare the incomplete struct type, I would expect this to fail:
Code: |
struct nodeB{
struct nodeA n;
int16 v;
};
|
But this to work:
Code: |
struct nodeB{
struct nodeA *p;
int16 v;
};
|
Does that makes sense?
Now I am curious how older C programmers doing complex data structures constructed nodes that cross reference each other. |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19619
|
|
Posted: Sat Apr 12, 2014 1:07 pm |
|
|
An alternative if this doesn't work, is just to declare either a long integer, or a pointer to another type, and then cast this to be a pointer to the structure you want after this is declared.
Best Wishes |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1362
|
|
Posted: Sat Apr 12, 2014 2:31 pm |
|
|
That's kind of what I was doing in the interim. I was using a void * and casting. I was trying to eliminate having to cast the type everywhere if possible. Alan's suggestion seems to work. I can only compile it at this time, but once I get to some hardware this week I can also test it out.
Thanks! This appears to do what I want. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1638 Location: Perth, Australia
|
|
Posted: Sat Apr 12, 2014 8:25 pm |
|
|
jeremiah wrote: |
While I understand that, I would have suspected declaring a pointer to an incomplete type would be fine since you aren't referencing size or elements of it to do that |
In traditional C this would have been a problem for pointer arithmetic so I am not surprised it did not work. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1362
|
|
Posted: Sat Apr 12, 2014 9:55 pm |
|
|
I'm not sure I can think of an example where pointer arithmetic happens in a variable declaration. I know once you proceed to assignment it could, but pointer declarations tend to be rather mundane in terms of requirements. You don't need to know the size of the pointer or anything about what it points to until you try to use it in some way (which is past the declaration stage). I would definitely expect pointer arithmetic to be an issue there, but in a declaration I'm not thinking of a scenario where that happens. Where would you run into that? |
|
|
|