Hot!warning: (2029) a function pointer cannot be used to hold the address of data

Page: < 123 Showing page 3 of 3
Author
qɥb
Monolothic Member
  • Total Posts : 660
  • Reward points : 0
  • Joined: 2017/09/09 05:07:30
  • Location: Jupiter
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/10 18:27:50 (permalink)
0
NKurzman
...
Note XC8 is Not GCC and follows the C89 Standard.  If you find it does not report it.

 
Correctly inserted comma makes all the difference. :)

Note XC8 is Not GCC and follows the C89 Standard.  If you find it does not, report it.


PicForum "it just works" (again)
#41
Peter Sikora
Senior Member
  • Total Posts : 95
  • Reward points : 0
  • Joined: 2003/11/07 12:46:46
  • Location: Brisbane Australia
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/12 23:01:47 (permalink)
0
/* Main.h */
/*/////////////////////////////////////////////////////////// DEFINES //////////////////////////////////////////////////////////*/
/* Forward declare a message struct prototype. It will allow the SYS_MSG data type to be used in the function call parameters
    If you miss this step compiler doesn't allow you to use SYS_MSG within function pointer declaration
*/
/* struct T_SYS_MSG; */ /* Note Alternate forward declaration also works with alternate function pointer declaration */
    typedef struct T_SYS_MSG SYS_MSG;
    
/* Now define the "Object Function Pointer" type. It must match the format of the function that it will point to
    OBJ_FUNC as function pointer to function that returns int and has SYS_MSG* as arguments.
    The compiler will create a data type "OBJ_FUNC" This can now be used to complete the SYS_MSG struct declaration
*/
/* typedef unsigned int (*OBJ_FUNC)( struct T_SYS_MSG*); */ /* Use with alternate struct declaration */
    typedef unsigned int (*OBJ_FUNC)( SYS_MSG*);
    
/* Complete the System Message Structure declaration assigning it's members. */
struct T_SYS_MSG{
int Type; /* Device responsible for the message used to TYPE the void pointer */
int Device; /* from list of possible I/O Devices */
int Event; /* Generic device event codes. */
int ObjID; /* ObjectID of Object */
int param1; /* Parameter 1 interpretation is 'device' dependent. */
int param2; /* Parameter 2 interpretation is 'device' dependent. */
OBJ_FUNC pObjFunc; /* function pointer to the object message function */
void* pObject; /* Object Pointer */
}SYS_MSG; /* System Message Struct Defined */

/* Declare a function pointer prototype to use with the function pointer of type OBJ_FUNC
 with parameters type SYS_MSG
*/

unsigned int (*pObjFunc)( SYS_MSG* pMsg);

/* Declare the function prototype. The structure must be identical to the one that will get called by the pointer
    This will be our test function
*/
unsigned int AFunction( SYS_MSG* );
 
/* EOF Main.h */

/* Main.c */
/*////////////////////////////////////////////////////////// VARIABLES /////////////////////////////////////////////////////////*/


/*-------------------------------------------------------------|130|------------------------------------------------------------*/
/*////////////////////////////////////////////////////// LOCAL PROTOTYPES //////////////////////////////////////////////////////*/

int main(void);

/**************************************************************|130|*************************************************************
/*/////////////////////////////////////////////////////////// HEADERS //////////////////////////////////////////////////////////*/
#include "Main.h"

/*/////////////////////////////////////////////////////////// DEFINES //////////////////////////////////////////////////////////*/


/*////////////////////////////////////////////////////// LOCAL PROTOTYPES //////////////////////////////////////////////////////*/

/* Description;
    Create a Struct that holds parameters and a function pointer to execute those parameters
*/
int main()
{
/*  Create a system message store   */
    SYS_MSG Msg;
/*  Assign a pointer to it  */
    SYS_MSG* pMsg = &Msg;
/* Variable to hold result of function call */
unsigned int Result;

/* Populate a simulated message store could be a linked list type buffer*/
Msg.Type = 0x01;                    /* Store Numeric parameters */
Msg.param1 = 20;
Msg.param2 = 30;
Msg.pObjFunc = AFunction;           /* Store Function Pointer to local function called AFunction */
 
/* Retrieve the saved function pointer and attempt to call the function */
pObjFunc = Msg.pObjFunc;            /*  Function Pointer type that matches the specific    */
                                    /*  function parameters we wish to call.  */
Result = (*pObjFunc)(pMsg);         /*  It so happens that the function we are calling will return an integer value  */
                                    /*  We can inspect the value is correct after the function returns in debug mode */

return 0;
} /* end main */
/*/////////////////////////////////////////////////////// LOCAL FUNCTIONS //////////////////////////////////////////////////////*/
unsigned int AFunction( SYS_MSG* pMsg ){
unsigned int A = pMsg->param1;
unsigned int B = pMsg->param2;
return (A + B);}
 
/* EOF Main.c */
 
/

 
If you paste this code into main and header files in Visual studio C it compiles and works as it should. It doesn't compile with XC16. The fault seems to be with XC16 not allowing to forward declare the struct that is ultimately used as parameters for the function. So if you can't forward declare the struct you can't use the function pointer type in the struct. I tried alternate declaration wording which also works with visual studio but still no joy with XC16.
I think I am following all the rules correctly and I don't understand why it won't compile with XC16. There is little to no information in the compiler user guide on function pointers.
#42
jtemples
Super Member
  • Total Posts : 10422
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/13 00:10:23 (permalink)
+2 (2)
Your code is not standard C.  Are you sure Visual Studio is running in C mode and not C++ mode?  Maybe what you're doing is legal in C++ or is a Visual Studio extension.
 
typedef struct T_SYS_MSG SYS_MSG;

 
This declares SYS_MSG as an alias for the struct T_SYS_MSG type.
 
struct T_SYS_MSG { int Type; ... } SYS_MSG;

 
This defines a struct object called SYS_MSG. But SYS_MSG has already been declared to be a typedef, and you can't have an object and a typedef with the same name.  I tried this code on a couple of C compilers, and they give errors like "storage class redeclared" and "SYS_MSG redeclared as different kind of symbol".
#43
jtemples
Super Member
  • Total Posts : 10422
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/13 00:24:48 (permalink)
+1 (1)
C does allow you to declare incomplete structs so that you can create pointers to them before they're fully declared:
struct tag;   // declares the "struct tag" type
struct tag *ptr;   // a pointer to a struct tag can be declared without knowing its members
struct tag { int a; };   // complete the definition sometime later

#44
Peter Sikora
Senior Member
  • Total Posts : 95
  • Reward points : 0
  • Joined: 2003/11/07 12:46:46
  • Location: Brisbane Australia
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/13 00:30:44 (permalink)
0
I looked up uni lectures to find similar examples for C and they all say to specify the struct as open type without brackets for a forward declaration so that the compiler has a name to assign to the object. This is supposed to be legal in C. And yes the code does compile correctly with XC32 V1.44 with one exception that while I was testing I forgot to put back the typedef  on struct T_SYS_MSG{.....members....}SYS_MSG; I just tried it out of interest and the code does simulate correctly with XC32. typedef struct T_SYS_MSG SYS_MSG; is an empty declaration ans is purely there to give the function pointer parameter a type. It should be legal to have an empty declaration. Other wise how do you include a function pointer as a member of a struct that has parameters that references the same struct. I put a support ticket in on the issue and will post the results.
#45
jtemples
Super Member
  • Total Posts : 10422
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/13 00:43:32 (permalink)
0
Were you running XC32 in C++ mode?
 
Other wise how do you include a function pointer as a member of a struct that has parameters that references the same struct.

 
That's what I showed you in post #44.  You can declare a pointer to a struct without the struct having been completely defined.
#46
Peter Sikora
Senior Member
  • Total Posts : 95
  • Reward points : 0
  • Joined: 2003/11/07 12:46:46
  • Location: Brisbane Australia
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/13 00:52:40 (permalink)
0
struct T_SYS_MSG; /* Note Alternate forward declaration also works with alternate function pointer declaration */

typedef unsigned int (*OBJ_FUNC)( struct T_SYS_MSG*); /* Use with alternate struct declaration */

typedef struct T_SYS_MSG{
....Struct Members
}SYS_MSG; /* System Message Struct Defined */

 
With these modifications the code compiles in XC32 with ANSI Strict enabled compiled as well.
and just to shoot myself in the foot I tried the same code again in XC16 to find it compiled without issue this time.
 
So why did it not work the first time round? Maybe it was the missing "typedef" Why do both methods work on XC32? maybe because XC32 has GCC++. Well at least I have a solution that I can fully understand the mechanisms of.
 
Thanks Jtemples for your input.
 
#47
Peter Sikora
Senior Member
  • Total Posts : 95
  • Reward points : 0
  • Joined: 2003/11/07 12:46:46
  • Location: Brisbane Australia
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/13 01:05:11 (permalink)
0
Re post 44. I got used to creating structs with a Tag and a name which are different. Maybe this is where my confusion and problems began. Visual studio is supposed to pick up on the file extension in determining if it compiles in C or C++ Now I am not sure if this is always the case. Now I will have to digest what I have learned.
#48
Peter Sikora
Senior Member
  • Total Posts : 95
  • Reward points : 0
  • Joined: 2003/11/07 12:46:46
  • Location: Brisbane Australia
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/14 14:38:34 (permalink)
0
@jtemples Thanks for shedding light on another issue with a linked list struct I was having.
It boils down to my using a different name for the struct [tag] and the struct typdef [name].
My struct consisted of the following defenition
typedef struct T_RECRD
.....other members.....
struct RECRD* pNextR; /* A pointer to the next record in list. */
}RECRD; /* Object Type RECORD Defined */

however when I tried to assign the members elsewhere in the program like this
pList->pNextR->pNextR = pList->pCurrent;

I would get an error saying warning: assignment from incompatible pointer type.
I would have to cast like this
pList->pNextR->pNextR = (struct RECRD*)pList->pCurrent;

The reason is that I was incorrectly using the typedef name to assign the member instead of the struct tag
The struct definition should have been like this.
typedef struct T_RECRD
.....other members.....
struct T_RECRD* pNextR; /* A pointer to the next record in list. */
}RECRD; /* Object Type RECORD Defined */

My error of understanding came from the fact that a lot of programmers who submit examples on the net use the same name for the struct [tag] and the typedef [name] which can lead to a misunderstanding of the way it works. once again many thanks to @jtemples and I hope this helps someone else.
 
 
 
#49
jtemples
Super Member
  • Total Posts : 10422
  • Reward points : 0
  • Joined: 2004/02/13 12:31:19
  • Location: Southern California
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/14 15:19:58 (permalink)
+2 (2)
typedef struct T_RECRD

 
This doesn't do anything.  It's syntactically legal, but it's equivalent to doing "typedef int;"  If you run this through a gcc-based compiler, you'll get a warning to that effect.
 
If you want to typedef a struct, you need to include the tag:
    typedef struct tag tag_t;
    tag_t *ptr;   // create a pointer without the full definition of the struct
    struct tag { int i; };   // complete the definition of the struct tag type
    tag_t s;   // define an object
Or include the struct definition in the declaration:
    typedef struct { int a; } not_a_tag;
    not_a_tag s;

Another thing that might cause confusion is the fact that tags have their own private namespace.  That means something like this is legal:
struct tag { int i; } tag;
which creates an object called "tag" and struct tag called "tag".  But you can't also have a typedef named "tag" which was the issue in your original code.
 
 
#50
Peter Sikora
Senior Member
  • Total Posts : 95
  • Reward points : 0
  • Joined: 2003/11/07 12:46:46
  • Location: Brisbane Australia
  • Status: offline
Re: warning: (2029) a function pointer cannot be used to hold the address of data 2018/01/14 16:13:11 (permalink)
+1 (1)
Much thanks. I was missing the opening brace when I pasted that in making it seem useless. it should have read like this
typedef struct T_RECRD{
.....other members.....
struct T_RECRD* pNextR; /* A pointer to the next record in list. */
}RECRD; /* Object Type RECORD Defined */

 
Cheers
#51
Page: < 123 Showing page 3 of 3
Jump to:
© 2018 APG vNext Commercial Version 4.5