Правильно ли C99, что вам не нужно указывать аргументы в объявлениях указателей функций в структурах?

StackOverflow https://stackoverflow.com/questions/2143315

  •  23-09-2019
  •  | 
  •  

Вопрос

Я написал следующий код на 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 компилятор.

Это было полезно?

Решение

Хотя это также работает в GCC с std=c99 -Wall -pedantic я удивлен, что он вообще компилируется, даже не предупредив об этом.На мой взгляд, это не очень круто.

Я считаю, что гораздо лучше использовать следующее:

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

Он компилируется под GCC 4.2 с использованием вышеуказанных переключателей.

В противном случае, глядя на ваш код, я вполне мог бы подумать, что вы совершаете ошибку, вызывая Push с двумя аргументами.Вышесказанное также компилирует и устраняет эту путаницу.

Другие советы

Это плохой стиль (хотя и законный).Это будет работать, но это означает, что компилятор не может проверить ваши аргументы.Итак, если вы случайно вызовете свою функцию следующим образом:

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

компилятор не сможет сказать вам, что вызов неправильный.

До стандартизации ANSI у K & R C не было прототипов;он поддерживал только объявления, в которых указывался возвращаемый тип.Когда вы опускаете аргументы, вы используете эту архаичную функцию.

В gcc вы можете использовать опцию -Wstrict-prototypes чтобы включить предупреждения при их использовании.

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;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top