我目前正在为微处理器编写C代码,而且我遇到了一些我无法解释的问题。我已经使用函数指针实现了一个命令行界面。为此,我创建了一个结构,其中包含命令的名称,指向要运行的函数的指针以及帮助描述。
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;
}
我已经包含了函数exec_command
的上方,这是函数指针的使用位置。在底部,我还提供了start_simulation
和stop_simulation
函数以及CmdLed
。我提前写了CmdLed
,然后回来写了start_simulation
和stop_simulation
。我忘记了我已经将我的函数指针定义为以(char *)
作为参数。然而,我惊讶地发现所有东西仍然编译并且运行得非常好。为什么是这样?似乎任何论点都被“倾销”了。并没有使用。
答案 0 :(得分:2)
这不应该用现代编译器编译。
这里会发生什么:
start_simulation
将使用char*
参数调用,但由于start_simulation
没有参数,因此该参数将被忽略(或在您编写时“转储”)。
请记住,在C函数中,参数被推入堆栈,调用者在调用后清理堆栈。因此,如果你调用一个没有参数的函数假装它有参数,那么
还要看this SO question。
答案 1 :(得分:1)
我假设您在使用它们之前声明了函数,或者您编译器隐含地声明它们为(C默认值):
int start_simulation();
...
意味着start_simulation
应该在其他地方定义为接受任何参数并返回int的函数。
但是这应该至少给你一些警告,因为定义与声明不同,或者函数声明与命令结构的第二个元素的命令声明不匹配(在const commandStruct commands[] = ...
中)
因为它编译并运行正常,传递参数的cdecl方式如下:
这意味着您可以随时添加未使用的参数,前提是编译器足够容忍编译错误的调用,或者使用空参数列表声明函数。