Function pointer arguments are ignored / not needed

I am currently writing C code for a microprocessor and I came across something that I could not explain. I have implemented the command line interface using function pointers. To do this, I created a structure containing the command name, a pointer to the function that will be run, and a description of the help.

typedef void(*command)(char *);
typedef struct commandStruct {
    char const *name;
    command execute;
    char const *help;
} commandStruct;

const commandStruct commands[] =
{
    {"led", CmdLed, "Turns on or off the LED1"},
    {"AT+START_SIM", start_simulation, "Starts the simulation"},
    {"AT+STOP_SIM", stop_simulation, "Stops the simulation"},
    {"",0,""} //End of table indicator.
};

void exec_command(char *buffer)
{
    uint16 i = 0;
    char *cmd = buffer;
    char *args;
    while (buffer[i])
    {
        if(buffer[i] == '=')
        {
            buffer[i] = 0;
            args = buffer + i + 1;
            break;
        }
        i++;
    }

    uint16 cmdCount = 0;
    while(strcmp(commands[cmdCount].name,""))
    {
        if(!strcmp(commands[cmdCount].name,cmd))
        {
            commands[cmdCount].execute(args);
            break;
        }
        cmdCount++;
    }
}

void start_simulation(void) {run = 1;}
void stop_simulation(void) {run = 0;}
void CmdLed(char *args)
{
    P1DIR |= BIT0;
    if(!strcmp(args,"on")) P1OUT = 1;
    if(!strcmp(args,"off")) P1OUT = 0;
}

      

I have included the above function exec_command

where the function pointer is used. At the bottom, I've also added functions start_simulation

and stop_simulation

along with CmdLed

. I wrote CmdLed

on an earlier date and then went back and wrote start_simulation

and stop_simulation

. I forgot that I defined my function pointer as an argument. However, I was surprised to find that everything is still compiled and working absolutely fine. Why is this? It seems that any arguments are simply "flushed" and not used.

+3


source to share


2 answers


It shouldn't compile with modern compilers.

What's going on here:

start_simulation

called with an argument char*

, but since start_simulation

it has no argument, the argument is simply ignored (or "flushed" on write).



Remember, in the arguments, C functions are pushed onto the stack and the caller clears the stack after the call. So if you call a function with no argument, pretending it has argument (s), then

  • the caller pushes the argument onto the stack
  • function with no arguments is called by the caller
  • the function makes it business by ignoring the argument (s) on the stack
  • functions are returned to the caller
  • the caller clears the stack

Also have a look at this SO question .

+2


source


I am assuming that either you declared your functions before using them, or the compiler implicitly declared them as (C by default):

int start_simulation();
...

      

The value start_simulation

must be defined elsewhere as a function that takes any parameters and returns an int.

But that should give you at least some warnings, because either the definition is different from the declaration, or the function declaration does not match the command declaration for the second command line item (c const commandStruct commands[] = ...

)



In order for it to compile and work fine, the path for passing cdecl parameters is as follows:

  • parameters are pushed onto the stack in the opposite order
  • called called call (caller return address is pushed onto the stack)
  • callle can get its parameters starting at the stack pointer + the size of the return address, but without removing them from the stack
  • returns request
  • caller removes the parameters it pushes onto the stack (it knows them)

This means that you can always add unused parameters if the compiler is tolerant enough to compile the wrong call or the function was declared with an empty parameter list.

+1


source







All Articles