代码之家  ›  专栏  ›  技术社区  ›  Gary Willoughby

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

  •  5
  • Gary Willoughby  · 技术社区  · 15 年前

    我已经编写了以下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”,而不是使用struct关键字和“stack”,来定义我当前正在定义的结构。

    我在用电话 Pelles C 编译器。

    3 回复  |  直到 15 年前
        1
  •  2
  •   zneak    15 年前

    虽然它在GCC下也有,但是 std=c99 -Wall -pedantic 甚至连警告都没有,我很惊讶它居然能编译。在我看来,这不太酷。

    我认为使用以下方法更好:

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

    它使用上述开关在GCC4.2下编译。

    否则,看看你的代码,我很可能认为你用两个参数调用Push是一个错误。上述内容也汇编并澄清了这种混淆。

        2
  •  5
  •   R Samuel Klatchko    15 年前

    这是一种糟糕的风格(尽管合法)。它可以工作,但这意味着编译器无法检查您的参数。因此,如果您意外地像这样调用函数:

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

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

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

        3
  •  1
  •   Trent    15 年前

    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;