是否正确C99,您不需要在结构中的函数指针声明中指定参数?

时间:2010-01-26 22:52:31

标签: c function-pointers c99

我编写了以下C99代码,并对结构声明感到疑惑。在其中我声明了两个函数指针,它们最终指向主代码中的两个push / pop方法。在函数指针声明中,我已经省略了参数,程序编译好了。它是否正确?我确定我已经读过必须提供的论据。这是正确的C99行为吗?

#include <stdio.h>

#define INITIAL_STACK_SIZE 1000

typedef struct stack
{
    int index;
    void *stack[INITIAL_STACK_SIZE];
    void* (*Pop)(); //<-- Is this correct?
    void (*Push)(); //<-- Is this correct?
} stack;

stack CreateStack(void);
void PushStack(stack*, void *);
void *PopStack(stack*);

stack CreateStack(void)
{
    stack s = {0, '\0'};
    s.Pop = PopStack;
    s.Push = PushStack;
    return s;
}

void PushStack(stack *s, void *value)
{
    if(s->index < INITIAL_STACK_SIZE)
    {
        s->stack[s->index++] = value;
    }
    else
    {
        fputs("ERROR: Stack Overflow!\n", stderr);
    }
}

void *PopStack(stack *s)
{
    if(s->index > 0)
    {
        return s->stack[--s->index];
    }
    else
    {
        fputs("ERROR: Stack Empty!\n", stderr);
        return NULL;
    }
}

int main(int argc, char *argv[])
{
    stack s = CreateStack();

    s.Push(&s, "Hello");
    s.Push(&s, "World");

    printf("%s\n", (char*)s.Pop(&s));
    printf("%s\n", (char*)s.Pop(&s));

    return 0;
}

我尝试将参数添加到函数指针但是我得到了Extraneous old-style parameter list.的编译器错误,所以我猜它是正确的,但是会喜欢另一种意见。

编辑:我遇到了上述“无关的旧式参数列表”错误,因为我使用的是typedef名称'stack'而不是使用带有'stack'的struct关键字来定义它是我当前定义的结构。

我正在使用Pelles C编译器。

3 个答案:

答案 0 :(得分:5)

这是不好的风格(虽然合法)。它会工作,但这意味着编译器无法检查您的参数。所以如果你不小心打电话给你的函数:

s.Push(arg, &s);   // oops, reverse the arguments

编译器无法告诉你通话不好。

在ANSI标准化之前,K&amp; R C没有原型;它只支持指定返回类型的声明。当你省略参数时,你正在使用这个古老的特征。

在gcc上,您可以使用选项-Wstrict-prototypes在使用时启用警告。

答案 1 :(得分:2)

虽然它在GCC下也只有std=c99 -Wall -pedantic而且没有任何警告,但我很惊讶它完全编译。在我看来,这不是很酷。

我相信使用以下内容会更好:

void* (*Pop)(struct stack*);
void (*Push)(struct stack*, void*);

使用上述开关在GCC 4.2下编译。

否则,看看你的代码,我很可能会认为你用两个参数调用Push会犯一个错误。以上也编译并清除了这种混乱。

答案 2 :(得分:1)

gcc(-pedantic -Wall -std=c99)对此代码没有问题:

typedef struct stack
{
 int index;
 void *stack[INITIAL_STACK_SIZE];
 void* (*Pop)(struct stack *);
 void (*Push)(struct stack *, void *);
} stack;