I am trying to pass a pointer by reference to a function and get that function to point my pointer at a structure that it finds.
char get_structure(STRUCTURE **ptr) { if(foundstructure) { *ptr = &theStructure; return 1; } return 0; }
This works how I expect it, but when I try and declare the function prototype in the header file:
char get_structure(STRUCTURE **ptr);
I always get a compiler error:
error C141: syntax error near '*', expected ')'
I don't get an error when this is a defined type like char, int or long, but I get the error when this is a pointer to a typedef that I have defined.
How can I declare this in my header file without an error?
Nathan
What if you replace STRUCTURE with "struct STRUCTURE"? Have you made sure that STRUCTURE is defined at that point in the header file?
Yes because the single pointer returns no error:
char get_structure(STRUCTURE *ptr); // == NO ERROR char get_structure(STRUCTURE **ptr); // == ERROR EVERY TIME char get_structure(char **ptr); // == NO ERROR
char get_structure( void **ptr );
... and some casting...?
Void works just find as well.
Which makes it look more like a problem with your definition of STRUCTURE.
Again, you're going to have to show a complete example for anyone to be able to help you with that...
How is this a problem with my structure? I've already made is clear that my code is executing and working fabulously. It is ONLY the function prototype that is having issues. The actual function declaration does not return any error. And using a single pointer returns no error. It is only the double pointer in the prototype declaration that returns an error.
How is this a problem with my structure? how can we tell when you do not show it.
I think you are getting too few errors rather than too many
"more words do not make you appear stupid they make you appear clear"
Erik
I can't post source code, because it would void my non-disclosure contract, but here's a post safe version:
Header file:
#define STRUCT_LEN 12 typedef union _STRUCTURE { unsigned char bytes[STRUCT_LEN]; struct _STRUCT1 { unsigned long field1; unsigned char field2; unsigned char field3; unsigned char field4; unsigned char field5; unsigned char field6[4]; } STRUCT1; struct _STRUCT2 { unsigned long field1; unsigned char field2; unsigned char field3; unsigned char field4; unsigned char field5; unsigned char field6; unsigned char field7; unsigned char field8; unsigned char field9; } STRUCT2; ... } STRUCTURE; uint8 function(STRUCTURE **ptr); //This is causing compile error C141
C file:
uint8 function(STRUCTURE **ptr) { if(...) { *ptr = &structure; return TRUE; } else return FALSE; }
I know it's not the structure that is the problem. This structure has been used in it's current state for over a year now in many implementations. It is only the double pointer in the prototype that is causing grief. I'm going to go with the void work around.
uint8 function(void **ptr) { if(...) { *ptr = (void *)(&structure); return TRUE; } else return FALSE; } uint8 function(void **ptr);
I would like someone from Keil to try this however. I am sure that there is a problem that should be fixed here.
I would like someone from Keil to try this however
if so, you are in the wrong place, Keil support does not monitor the forum
contact Keil support directly
I know it's not the structure that is the problem. This structure has been used in it's current state for over a year now in many implementations. It is only the double pointer in the prototype that is causing grief.
Actually, no, it's not. If you put that exact code into (minus the syntax error '...', and plus a typedef for uint8) into an empty file, and compile that, it works just fine and dandy (uV4, C51 9.02). Which goes to show that whatever the problem actually is, it's not what you claim it is.
So, next try: show an actual, self-contained example that demonstrates the error.
In that case, you'd still to have to give them something to try!
Specifically, You'd have to give them a minimal but complete example that demonstrates the issue. You should be able to do that with non-confidential code. And you could share that on the foum.
main.c:
#include "struct.h" #include "function.c" STRUCTURE *structPtr; void main(void) { while(1) { get_struct(&structPtr); } return; }
struct.h:
#ifndef __STRUCT_H #define __STRUCT_H #include "function.h" typedef union _STRUCTURE { unsigned char fields[2]; struct _NAMED { unsigned char field1; unsigned char field2; } NAMED; } STRUCTURE; #endif
function.h
#ifndef __FUNCTION_H #define __FUNCTION_H void get_struct(STRUCTURE **myStruct); #endif
function.c
#ifndef __FUNCTION_C #define __FUNCTION_C #include "struct.h" #include "function.h" STRUCTURE myStruct; void get_struct(STRUCTURE **strPtr) { *strPtr = &myStruct; } #endif
As you can see my problem is that I have a circular header reference "struct.h" includes "function.h" and "function.h" includes "struct.h". The example doesn't show it, but "struct.h" needs to include "function.h" because there is an enum declared in "function.h" that is part of the structure in "struct.h". I believe this can be solved using forward declarations, but I have not had any success yet.
So maybe:
#ifndef __FUNCTION_H #define __FUNCTION_H void get_struct(union _STRUCTURE **myStruct); #endif
By the way - from the first response you got to your issue: "Have you made sure that STRUCTURE is defined at that point in the header file?"
Including .c source files is almost always the wrong thing to do.
main.c should include function.h, not function.c. struct.h is not dependent upon function.h, so should not include function.h. function.h is dependent upon struct.h to fully publish get_struct()'s interface, so should include struct.h. function.c should not be included by anything, so does not need include guards, and needs to be added to the project's list of .c source files for separate compilation and linking.
I mentioned in my post that although the example doesn't show it, struct.h does depend on function.h. There is an enum that is declared in function.h that is used in STRUCTURE.
Revised Example:
#ifndef __STRUCT_H #define __STRUCT_H #include "function.h" typedef union _STRUCTURE { unsigned char fields[2]; struct _NAMED { unsigned char field1; ENUMERATION field2; } NAMED; } STRUCTURE; #endif
function.h:
#ifndef __FUNCTION_H #define __FUNCTION_H typedef enum _ENUMERATION { ONE = 1, TWO = 2 } ENUMERATION; void get_struct(STRUCTURE **myStruct); #endif
function.c:
Adding function.c to the project and changing the include to function.h instead of function.c did not solve the problem.
Thanks very much. This solved the issue. Is there a term used for this type of reference?
Also I'm positive that I was getting no such error in V9.01 when making reference to STRUCTURE except when used in the double pointer scenario.
After the update I could make no reference to STRUCTURE without an error being thrown.
"Adding function.c to the project and changing the include to function.h instead of function.c did not solve the problem."
Had you followed all the instructions, you would have seen that it solved the problem in the code you posted.
"I mentioned in my post that although the example doesn't show it, struct.h does depend on function.h. There is an enum that is declared in function.h that is used in STRUCTURE."
Making your first example a waste of time. Now that you've posted a complete example demonstrating your problem, I've made a few small edits:
main.c should include function.h, not function.c. function.h is dependent upon struct.h to fully publish get_struct()'s interface, so should include struct.h. function.c should not be included by anything, so does not need include guards, and needs to be added to the project's list of .c source files for separate compilation and linking.
#include "struct.h" #include "function.h" STRUCTURE *structPtr; void main(void) { while(1) { get_struct(&structPtr); } return; }
#ifndef __FUNCTION_H #define __FUNCTION_H typedef enum _ENUMERATION { ONE = 1, TWO = 2 } ENUMERATION; #include "struct.h" void get_struct(union _STRUCTURE **myStruct); #endif
#include "struct.h" #include "function.h" STRUCTURE myStruct; void get_struct(STRUCTURE **strPtr) { *strPtr = &myStruct; }
One sidenote is that your use of identifiers with leading underscores risks treading on the implementor's reserved namespace.
Duly noted, but those edits do not fix the problem either. Compiler is still throwing the C141 error. Only if I declare the prototype like this do I avoid the error:
void get_struct(union _STRUCTURE **myStruct);
"Only if I declare the prototype like this do I avoid the error:
And the prototype in the function.h I posted is:
How do they differ?
Sorry, I thought you were offering a solution to solve the problem.
Thanks again to Per Westermark.
"Sorry, I thought you were offering a solution to solve the problem."
Oh, good grief!
*plonk*
I mentioned in my post that although the example doesn't show it, struct.h does depend on function.h.
Circular dependencies are a design bug in your software. You must resolve that.
Generally speaking, when you can't decide whether "a.h" should include "b.h" or the other way round, that's a strong indication that your design is wrong, and you should really have only one header holding the combined content of both "a.h" and "b.h".
There is an enum that is declared in function.h that is used in STRUCTURE.
Then the definition of that enum should not be in "function.h". It belongs into "struct.h".
I recommend you spend some time with the C language standard. The use of "struct <structname>*" is specifically allowed to be used before the full description of the structure is seen just to avoid problems with circular references.
The thing is that a struct <structname>* is a pointer of known size - as long as you don't try to follow that pointer, you don't need to know how large the struct is, or what member fields it has. If we ignore the issue with specific addressable memory regions in the 8051 processor architecture, or memory models with small/medium/large/huge/... pointers, the size of a pointer to struct is the same what ever the type the struct has. And the word "struct" or "union" before the tag name is enough that the compiler understands that the tag name is the name of a structure or union type. Just seeing "STRUCTURE", the compiler don't know it's one of your own data types. And it's not a known keyword. So the compiler don't know what to do. Your code as written is invalid C code. And the compiler did complain.
#ifndef __STRUCT_H #define __STRUCT_H #include "function.h" typedef union _STRUCTURE { unsigned char fields[2]; struct _NAMED
Before I forget, one other issue: you need to revisit your naming conventions.
All names starting with two underscores (like __STRUCT_H), and those starting with an underscore followed by an uppercase letter (like _STRUCTURE and _NAMED) are reserved to the implementation. Application code (i.e.: yours) is not supposed to use them.
Bewildering problems like yours can be caused quite easily by violating those rules. People have wasted days of head-scratching trying to figure out what was going on in such cases. E.g. the C compiler has been given explicit licence to predefine _STRUCTURE as the number 7 --- guess you wouldn't like what that would do to your code.
This kind of refactoring isn't possible right now, but rest assured I am aware that this file structure is inadequate. This isn't my project, it's an existing project that someone else created. I am avoiding the use of underscores before defined names now as well. Thanks for both those tips.
View all questions in Keil forum