5

我编写了以下 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.所以我猜它是正确的,但会喜欢另一种意见。

编辑:我遇到了上述'Extraneous old-style parameter list'错误,因为我使用typedef名称'stack'而不是使用带有'stack'的struct关键字来定义它是我当前定义的结构。

我正在使用Pelles C编译器。

4

3 回答 3

5

那是不好的风格(尽管是合法的)。它会起作用,但这意味着编译器无法检查您的参数。所以如果你不小心这样调用你的函数:

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

编译器将无法告诉您调用是错误的。

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

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

于 2010-01-26T22:59:27.943 回答
2

尽管它在 GCC 下也可以std=c99 -Wall -pedantic运行,甚至没有任何警告,但我很惊讶它完全可以编译。在我看来,这不是很酷。

我相信使用以下内容是一个更好的主意:

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

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

否则,查看您的代码,我很可能认为您使用两个参数调用 Push 是错误的。以上内容也编译并消除了这种混淆。

于 2010-01-26T23:02:39.437 回答
1

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

typedef struct stack
{
 int index;
 void *stack[INITIAL_STACK_SIZE];
 void* (*Pop)(struct stack *);
 void (*Push)(struct stack *, void *);
} stack;
于 2010-01-26T23:01:02.200 回答