Hello
I've a problem when initializing a global function pointer. Depending on where the function pointer is created, the adress of the funciton pointer is 0 (=wrong). There are no warnings in the compiler! Compiler: c166 v4.23 Tool: uVision2 v2.31
Example:
typedef UINT16 (*pModul_Para)(UINT16, UINT16 *, void *, UINT16);
//prototype of the function UINT16 Controller_Para(UINT16 ParamNr, UINT16 *pElementNr, void *pValue, UINT16 Action);
//create and init the function pointer pModul_Para FunctionPtr123 = &Controller_Para;
//Function definition UINT16 Controller_Para(UINT16 ParamNr, UINT16 *pElementNr, void *pValue, UINT16 Action) { ... }
//create and init a second function pointer pModul_Para FunctionPtr55 = &Controller_Para;
--> Result: FunctionPtr123 would be 0, FunctionPtr55 can be the address of Controller_Para.
Any idea? Thanks!
Hi Per,
Many thanks for the %p information.
I regularly find out that, I am not a competent C programmer. :>
I also did some quick search, %p is for "Print a void * (pointer to void) in an implementation-defined format."
as you mentioned in other thread, (Harvard architecture) data pointers and function pointers could be different in size. So I think the usage of %p would be quite complex to me.
And actually, the variable number of arguments of printf() is something that I have never understood.
In fact, different types of data pointers could be different in size!
eg, in C51, an XDATA pointer is larger than an IDATA pointer.
Some implementations provide "near" and "far" pointers
"the variable number of arguments of printf() is something that I have never understood"
That is a standard part of the 'C' programming language - not specific to Keil. Therefore, and general 'C' reference material should be relevant...
Hi R K,
Could you please explain more about how do you "read the contents of the address via an RS232 communication."?
I have a self-made tool (on PC) which read the list file (.m66). This file contains the addresses of all the variables. I select with my self-made tool a variable (or a pointer) -> the tool send a RS-232 string with the adress to the microcontroller. So my C166 program on the microcontroller read with the keil function HVAR() (HVAR = read from a absolute memory address) the value of the variable and send a string with the variable content back to my computer.
I have a self-made tool (on PC) ...
Sounds like a self-made rudimentary in-circuit debugger. A full-featured debugger would be more convenient. Anyway, the ultimate test would be to actually use the contents of the variable in your program. Like in a call to printf(). It could still be compiler optimization at work. Although I don't remember seeing any wonders of optimization from the C166 compiler.
Anyway, the ultimate test would be to actually use the contents of the variable in your program. Like in a call to printf(). It could still be compiler optimization at work.
When I try to call the function with the "wrong" pFunktionPointer_1 then the program will crash. So I only read the function pointer (without calling it) with function Test() Result: pFunktionPointer_12 = 0 (wrong !!!) pFunktionPointer_22 = correct pFunktionPointer_32 = correct
#include <STDLIB.H> //Typedef of the function pointer typedef unsigned int (*pModul_Parameter)(unsigned int, unsigned int *, void *, unsigned int); //prototype of the function below unsigned int CallThisFunction(unsigned int ParamNr, unsigned int *pElementNr, void *pValue, unsigned int Action); //create and init the function pointer 1 pModul_Parameter pFunktionPointer_1 = &CallThisFunction; //prototype of the function below unsigned int CallThisFunction(unsigned int ParamNr, unsigned int *pElementNr, void *pValue, unsigned int Action); //create and init the function pointer 2 pModul_Parameter pFunktionPointer_2 = &CallThisFunction; unsigned int CallThisFunction(unsigned int ParamNr, unsigned int *pElementNr, void *pValue, unsigned int Action) { //Do anything static int q = 88; return ++q; } //create and init the function pointer 3 pModul_Parameter pFunktionPointer_3 = &CallThisFunction; void Test(void) { static pModul_Parameter pFunktionPointer_12, pFunktionPointer_22, pFunktionPointer_32; pFunktionPointer_12 = pFunktionPointer_1; pFunktionPointer_22 = pFunktionPointer_2; pFunktionPointer_32 = pFunktionPointer_3; }
John Linq,
Could you post a link to that thread? I'd like to read it. Thanks.
So I only read the function pointer (without calling it) with function Test()
That's insufficient. Your program must produce observable "side effects" that depend on the value of the variable, according to the C standard.
When I try to call the function with the "wrong" pFunktionPointer_1 then the program will crash.
That would probably qualify as a real "side effect". Although we didn't see the actual code.
As I said before, this is probably a compiler and/or linker bug.
I forgot to mention that compiler/linker bugs should be reported to Keil. You can wait for a fix from them (requires a support contract, I think.) In the meantime, you can use some kind of a workaround. I think you found one: extra function prototypes and variables isolate the bug to a controllable area.
Hi Tamir,
Tried quite a while to find that thread, but no luck; will re-try with other keywords later.
"In fact, different types of data pointers could be different in size!"
Which is a reason why %p often supports a size parameter to specify what kind of pointer to print. Quite a number of architectures have more than one type or size of pointers.
To Tamir, the mentioned thread:
http://www.keil.com/forum/17103/
Per Westermark 24-Jun-2010 13:20 GMT
There is a rule that "A pointer to void may be converted to or from a pointer to any incomplete or object type." So you may typecast between a void pointer and some other data type.
But when an architectire have __far, __near, __code, __data, __base etc, it isn't automagically possible to store all pointers as a char pointer (or as a void pointer).
This means that void* isn't an automagic solution that can handle anything for real platforms even if the standard somehow implies this. It may be compatible with a function pointer. But what if you have a memory model where code is large and data is small - so a function pointer may need a larger size than a char* pointer. For old 16-bit x86 code, char* is byte-aligned byt in "compact" memory model it is 16 bit large while a function pointer is 32-bit large.
Hans-Bernhardn Broeker 24-Jun-2010 17:49 GMT
The C programming languages supports Harvard architecures, and that means code and data pointers are assumed to be fundamentally different things. There is no allowed way to convert from one to the other.
Thanks.