| Details |
Message |
|
Read-Only
Author Nathan Illerbrun
Posted 2-Mar-2012 22:41 GMT
Toolset C51
|
 Double pointer as parameter doesn't work with typedef
Nathan Illerbrun
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
|
|
|
Read-Only
Author Per Westermark
Posted 2-Mar-2012 22:54 GMT
Toolset C51
|
 RE: Double pointer as parameter doesn't work with typedef
Per Westermark
What if you replace STRUCTURE with "struct STRUCTURE"? Have you
made sure that STRUCTURE is defined at that point in the header
file?
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 2-Mar-2012 22:59 GMT
Toolset C51
|
 RE: Double pointer as parameter doesn't work with typedef
Nathan Illerbrun
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
|
|
|
Read-Only
Author Andrew Neil
Posted 3-Mar-2012 07:13 GMT
Toolset C51
|
 Workaround?
Andrew Neil
char get_structure( void **ptr );
... and some casting...?
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 5-Mar-2012 18:26 GMT
Toolset C51
|
 RE: Workaround?
Nathan Illerbrun
Void works just find as well.
|
|
|
Read-Only
Author Andrew Neil
Posted 5-Mar-2012 18:39 GMT
Toolset None
|
 RE: Void works just find (sic) as well.
Andrew Neil
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...
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 5-Mar-2012 18:51 GMT
Toolset None
|
 RE: Void works just find (sic) as well.
Nathan Illerbrun
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.
|
|
|
Read-Only
Author erik malund
Posted 5-Mar-2012 19:16 GMT
Toolset None
|
 how can we tell
erik malund
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
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 5-Mar-2012 19:57 GMT
Toolset None
|
 RE: how can we tell
Nathan Illerbrun
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.
|
|
|
Read-Only
Author erik malund
Posted 5-Mar-2012 20:10 GMT
Toolset None
|
 if so, you are in the wrong place
erik malund
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
|
|
|
Read-Only
Author Hans-Bernhard Broeker
Posted 5-Mar-2012 21:52 GMT
Toolset None
|
 RE: how can we tell
Hans-Bernhard Broeker
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.
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 6-Mar-2012 00:55 GMT
Toolset None
|
 RE: how can we tell
Nathan Illerbrun
I seem to be dealing with an include/linker error. The structure
is not defined at that point in the header file. I was sure I tested
this by declaring the parameter by value and by reference, and the
error would only show up by pointer reference (double pointer). Since
yesterday I updated to 9.05 an now all 3 are returning the C141
error. The forward declaration as someone mentioned doesn't work
though... will post again when I've solved this.
|
|
|
Read-Only
Author Andrew Neil
Posted 6-Mar-2012 00:36 GMT
Toolset None
|
 RE: I would like someone from Keil to try this
Andrew Neil
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.
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 6-Mar-2012 01:38 GMT
Toolset None
|
 RE: I would like someone from Keil to try this
Nathan Illerbrun
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.
|
|
|
Read-Only
Author Per Westermark
Posted 6-Mar-2012 07:22 GMT
Toolset None
|
 RE: I would like someone from Keil to try this
Per Westermark
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?"
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 6-Mar-2012 17:53 GMT
Toolset None
|
 RE: I would like someone from Keil to try this
Nathan Illerbrun
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.
char get_structure(STRUCTURE *ptr); // == NO ERROR
char get_structure(STRUCTURE **ptr); // == ERROR EVERY TIME
char get_structure(char **ptr); // == NO ERROR
After the update I could make no reference to STRUCTURE without an
error being thrown.
|
|
|
Read-Only
Author Per Westermark
Posted 6-Mar-2012 21:59 GMT
Toolset None
|
 RE: I would like someone from Keil to try this
Per Westermark
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.
|
|
|
Read-Only
Author Dan Henry
Posted 6-Mar-2012 12:37 GMT
Toolset None
|
 RE: ... my problem is ...
Dan Henry
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.
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 6-Mar-2012 17:37 GMT
Toolset None
|
 RE: ... my problem is ...
Nathan Illerbrun
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:
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;
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:
#ifndef __FUNCTION_C
#define __FUNCTION_C
#include "struct.h"
#include "function.h"
STRUCTURE myStruct;
void get_struct(STRUCTURE **strPtr)
{
*strPtr = &myStruct;
}
#endif
Adding function.c to the project and changing the include to
function.h instead of function.c did not solve the problem.
|
|
|
Read-Only
Author Dan Henry
Posted 6-Mar-2012 18:04 GMT
Toolset None
|
 RE: ... my problem is ...
Dan Henry
"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:
Including .c source files is almost always the wrong thing to
do.
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.
main.c:
#include "struct.h"
#include "function.h"
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;
ENUMERATION field2;
} NAMED;
} STRUCTURE;
#endif
function.h:
#ifndef __FUNCTION_H
#define __FUNCTION_H
typedef enum _ENUMERATION
{
ONE = 1,
TWO = 2
} ENUMERATION;
#include "struct.h"
void get_struct(union _STRUCTURE **myStruct);
#endif
function.c:
#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.
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 6-Mar-2012 18:25 GMT
Toolset None
|
 RE: ... my problem is ...
Nathan Illerbrun
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);
|
|
|
Read-Only
Author Dan Henry
Posted 6-Mar-2012 18:35 GMT
Toolset None
|
 RE: ... my problem is ...
Dan Henry
"Only if I declare the prototype like this do I avoid the
error:
void get_struct(union _STRUCTURE **myStruct);
And the prototype in the function.h I posted is:
void get_struct(union _STRUCTURE **myStruct);
How do they differ?
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 6-Mar-2012 18:43 GMT
Toolset None
|
 RE: ... my problem is ...
Nathan Illerbrun
Sorry, I thought you were offering a solution to solve the
problem.
Thanks again to Per Westermark.
|
|
|
Read-Only
Author Dan Henry
Posted 6-Mar-2012 18:49 GMT
Toolset None
|
 RE: ... my problem is ...
Dan Henry
"Sorry, I thought you were offering a solution to solve the
problem."
Oh, good grief!
*plonk*
|
|
|
Read-Only
Author Hans-Bernhard Broeker
Posted 6-Mar-2012 21:11 GMT
Toolset None
|
 RE: ... my problem is ...
Hans-Bernhard Broeker
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".
|
|
|
Read-Only
Author Nathan Illerbrun
Posted 6-Mar-2012 23:08 GMT
Toolset None
|
 RE: ... my problem is ...
Nathan Illerbrun
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.
|
|
|
Read-Only
Author Hans-Bernhard Broeker
Posted 6-Mar-2012 22:55 GMT
Toolset None
|
 RE: I would like someone from Keil to try this
Hans-Bernhard Broeker
#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.
|
|
|
Read-Only
Author Hans-Bernhard Broeker
Posted 3-Mar-2012 10:24 GMT
Toolset C51
|
 RE: Double pointer as parameter doesn't work with typedef
Hans-Bernhard Broeker
You really will have to show a complete example
demonstrating this. Without actually seeing how you defined
STRUCTURE, there's no way anyone can help you. I'll venture a guess
though: STRUCTURE is not actually a typedef, it's a #define, and
therein lies your problem.
And don't be too embarrassed if, while composing that example. the
cause of the problem jusmps out at you and you feel tempted to yell
at yourself "How could you possibly overlook that, stupid!" That does
happen to the best of us.
|
|
|
Read-Only
Author Andrew Neil
Posted 3-Mar-2012 12:07 GMT
Toolset None
|
 RE: while composing that example, the cause of the problem jumps out at you
Andrew Neil
"That does happen to the best of us"
Indeed it does!
The process of creating an example which illustrates the problem -
and only the problem - certainly can focus the mind and bring the
solution to light all by itself!
See: http://www.8052.com/forum/read/100837
|
|
|
Read-Only
Author Tamir Michael
Posted 3-Mar-2012 12:45 GMT
Toolset None
|
 RE: while composing that example, the cause of the problem jumps out at you
Tamir Michael
The process of creating an example which illustrates the
problem - and only the problem - certainly can focus the mind and
bring the solution to light all by itself!
Absolutely. See this thread - nobody believed me at the beginning,
until it was confirmed and fixed...
http://www.keil.com/forum/15346/
|
|
|
Read-Only
Author S Steve
Posted 3-Mar-2012 15:31 GMT
Toolset None
|
 And what about the other one?
S Steve
Absolutely. See this thread - nobody believed me at the
beginning, until it was confirmed and fixed...
http://www.keil.com/forum/19955/
|
|
|
Read-Only
Author Only human Zeusti
Posted 3-Mar-2012 20:52 GMT
Toolset None
|
 Even the best can make an mistake
Only human Zeusti
<quote>
"That does happen to the best of us"
</quote>
Yes indeed. It is proberbly hard for you to believe this but once
it even happened to me.
But as I tell my team 'the only of you who doesnt make mistakes is
the one who does nothing'.
Always yo're freind.
Zeusti.
|
|
|
Read-Only
Author Erik Malund
Posted 3-Mar-2012 14:32 GMT
Toolset C51
|
 C51?
Erik Malund
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)
are you one of those "C is C whatever it runs on" types?
if you look at the C51 assembler the above will generate,
you will realize that "C is C whatever it runs on" is a very bad
mantra when working with this architecture. There is absolutely
nothing wrong with programming the '51 in C (I have, probably,
written 100,000 lines of it) but do think of the architecture when
designing the code.
Erik
|
|