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

How to solove warning recursive call to a constant

I have following codes:

void fun1(unsigned char *msg);

void fun2()
{
fun1("ssss");
}
void fun3()
{
}
code void (*func_array[])()={fun2, fun3};

void fun1( unsigned char *msg)
{
(*func_array[1])();
}

void main()
{
(*fun_array[0])();
}

when compiling, i got the following message
*** WARNING L13: RECURSIVE CALL TO SEGMENT
SEGMENT: ?CO?HELLO

Could you please tell me how to solve it? Thanks a lot!

Parents Reply Children
  • use two function pointer tables

    That is PC C, not '51 C

    Mend your ways and adapt your coding style to the processor you are using. Practices like that can kill a '51 better than a voltage surge.

    Erik

  • If the techniques in the aforementioned App. Note #129 do not suit you, an alternative is to codify the function pointer array at the cost of an additional pushed return address.

    void func_array(unsigned char idx)
    {
        switch (idx)
        {
        case 0: fun2(); break;
        case 1: fun3(); break;
        case 2: fun4(); break;
        case 3: fun5(); break;
        case 4: fun6(); break;
        /* ... */
        }
    }
    

  • "...codify the function pointer array..."

    That is, if your function pointer arrays are constant (i.e., are not modified during runtime).

  • If you dynamically update the function pointer table, then there is no way for the static call tree analysis to help you. So, you'll be in for a lot of work with the OVERLAY directive, or else a lot of code bloat from the reentrant declaration. Unless you're doing extremely dynamic things like creating code to execute on the fly, you probably know the range of possible results, and can use an index into a table of fixed pointers. "Call func 3" works about as well as "Call func *p" in most cases.

    It's perhaps worth noting that a switch statement such as the one Dan posted generally compiles into a jump table anyway. You don't have to explicitly code a function pointer table to get a table of function pointers.

    I often get a recursive call to segment warning from code with structure like this:

    char const code * code StringTable[] =
       {
       "Name1",
       "Name2"
       }
    
    void f1 (int i)
       {
       printf (StringTable[i]);
       }
    
    void f2 (int i)
       {
       PerformWonders(i);
       }
    
    const code FuncTableEntry FuncTable[2] =
       { f1, f2 };
    
    void Dispatcher (void)
       {
       FuncTable(i);
       }
    

    That is, to be more brief, a const table of function pointers in a particular module. The Keil compile can figure out the call tree below Dispatcher, because the table is static file scope and constant. However, the function pointer table and the string constants reside in the same constant segment. So, f1 and f2 are marked as referring to their own segment, because of the reference to the string constants, and the linker thus dutifully produces a warning about recursive calls. There are no actual recursive calls in the code per se, just a reference from one item in the constant segment to another.

    There is no way to identify and selectively disable warning 13 in just these cases, so I unfortunately wind up shutting down all the recursive warnings. The alternative would be to break out the string constants and function table into seperate .c files so that they can appear in different segments, but that brings along all the usual problems of namespace clutter and lack of modularity that we're used to seeing in the "eliminate dead code" threads.

  • Dan: "... codify the function pointer array at the cost of an additional pushed return address."

    Drew: "It's perhaps worth noting that a switch statement such as the one Dan posted generally compiles into a jump table anyway."

    And when it compiles into a jump table, it does not cost an additional pushed return address.