5

次の C99 コードを書きましたが、構造体宣言について疑問に思っていました。その中で、メイン コードの 2 つのプッシュ/ポップ メソッドを最終的に指す 2 つの関数ポインターを宣言します。関数ポインターの宣言では、引数を省略しましたが、プログラムは正常にコンパイルされます。これは正しいです?引数を指定する必要があることを読んだと確信しています。これは正しい 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」エラーが発生しました。これは、「stack」で struct キーワードを使用するのではなく、typedef 名「stack」を使用して、現在定義している構造であると定義したためです。

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

GCCstd=c99 -Wall -pedanticでも警告なしで動作しますが、まったくコンパイルされることに驚きました。私の意見では、それはあまりクールではありません。

以下を使用する方がはるかに優れていると思います。

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

上記のスイッチを使用して、GCC 4.2 でコンパイルします。

そうでなければ、あなたのコードを見ると、Push を 2 つの引数で呼び出して間違いを犯していると考えることができます。上記もコンパイルしてその混乱を解消します。

于 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 に答える