This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problems with init of a function pointer

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!

  • First, please follow the instructions for posting source code.

    As this picture shows, they are really quite simple and clearly stated: www.danlhenry.com/.../keil_code.png

    Next, you need to show a complete example that illustrates your problem: 'C' doesn't allow executable statements in isolation - they have to be within a function!

  • Ok, thanks for the correction. I admittedly have not followed the forum rules, sorry! Next time I'll follow the rules!

    To my problem/your answer: Why can I not set the function pointer outside the function? The address of the function Controller_Para() should be available!? In case of a simple global variable, its no problem to set a constant value!

    unsigned int a = 555;
    

    Thank you

  • Why can I not set the function pointer outside the function? The address of the function Controller_Para() should be available!?

    If that is really the case, it would be a compiler/linker bug. Pointers to functions are allowed in initializers by ANSI C, and C166 claims ANSI C compliance.

  • It's not that it's not possible - but you didn't provide any evidence that you'd actually done it correctly in your code.

  • It's not that it's not possible - but you didn't provide any evidence that you'd actually done it correctly in your code.

    I've noticed that in my original code are two equal prototype of the function (1 time in the header file, 1 time in the C file above). This should have no influence on the function of the program!

    I've created a new c.-File with two function prototypes.
    Result:
    pFunktionPointer_1 = 0 (wrong !!!???)
    pModul_Parameter pFunktionPointer_2 = 292384 (correct !!!)
    pModul_Parameter pFunktionPointer_3 = 292384 (correct !!!)

    #include <stdio.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;
    

  • Hi r k,

    How do you get the values of pFunktionPointer_1, pFunktionPointer_2, pFunktionPointer_3?

    On the X86 platform, I can simply do this:

    int main(void)
    {
            printf("pFunktionPointer_1 = %d\n", pFunktionPointer_1);
            printf("pFunktionPointer_2 = %d\n", pFunktionPointer_2);
            printf("pFunktionPointer_3 = %d\n", pFunktionPointer_3);
            system("PAUSE");
            return 0;
    }
    

    But on the C166 platform, How do you get the values?

  • ran on C51 and ptr_1/2/3 point to the same thing.

    not sure about C166.

  • not sure about C166. but on C51, you just step through the code and watch the pointers.

  • Most compilers have a %p for printing pointers - potentially with a size flag to specify what type of pointer to print.

  • 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.

  • Hello

    I don't use printf or like this. I can see the adress of the pointer in the list file (.m66). So I read the contents of the address via an RS232 communication.

    Thank you for the efforts!

  • 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."?

  • 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.