2010-01-26 5 views
5

He escrito el siguiente código C99 y me preguntaba sobre la declaración struct. En él, declaro dos punteros a función que finalmente apuntan a los dos métodos push/pop en el código principal. En las declaraciones del puntero a la función, he omitido los argumentos y el programa compila bien. ¿Es esto correcto? Estoy seguro de que he leído que los argumentos deben ser proporcionados. ¿Es este comportamiento correcto de C99?¿Es correcto C99 que no necesite especificar argumentos en declaraciones de puntero a función en estructuras?

#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; 
} 

He intentado añadir los argumentos de los punteros de función, pero tengo un error de compilación de Extraneous old-style parameter list. así que supongo que es correcto, pero le encantaría otra opinión.

EDIT: Estaba experimentando el error 'Extraño de lista de parámetros antiguos' porque estaba usando el nombredef 'pila' en lugar de usar la palabra clave struct con 'pila' para definir que era la estructura que actualmente estoy definiendo .

Estoy usando el compilador Pelles C.

Respuesta

2

A pesar de que también lo hace en virtud de GCC con std=c99 -Wall -pedantic sin ni siquiera una advertencia sobre ello, me sorprende que se compila en absoluto. En mi opinión, eso no es muy bueno.

Creo que es una idea mucho mejor usar el siguiente:

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

lo hace bajo compilar GCC 4.2 mediante los conmutadores anteriores.

De lo contrario, mirando su código, podría pensar que está cometiendo un error llamando a Push con dos argumentos. Lo anterior también compila y borra esa confusión.

+0

De hecho, estaba cometiendo un error en mi código. Estaba usando el nombre typedef 'stack' en lugar de usar la palabra clave struct con 'stack' para definir que era la estructura que actualmente estoy definiendo. Gracias. –

+0

Sí, cometí el mismo error la primera vez que lo intenté, así que pensé que ese podría haber sido tu problema también. – zneak

+0

No fue grosero, pero di la misma respuesta dos minutos antes de zneak. – Trent

5

Ese es el mal estilo (aunque legal). Funcionará pero significa que el compilador no puede verificar tus argumentos. Así que si accidentalmente llama a su función como esta:

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

el compilador no será capaz de decir que la llamada es mala.

Antes de la estandarización ANSI, K & R C no tenía prototipos; solo admitía declaraciones que especificaban el tipo de devolución. Cuando dejas de lado los argumentos, estás usando esta característica arcaica.

En gcc, puede usar la opción -Wstrict-prototypes para activar las advertencias cuando las usa.

+0

Y use -Withsing-prototypes too too. –

1

gcc (con -pedantic -Wall -std=c99) no tiene ningún problema con este código:

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

gcc requiere el '-Wstrict-prototypes' para habilitar las advertencias de que la declaración de la función no es un prototipo. –

+0

@R Samuel Klatchko, no estoy seguro de lo que quiere decir, estoy demostrando que el código con los argumentos adecuados se compila con gcc (aunque informó que falla con el suyo) – Trent

+0

'-Wstrict-prototypes' captaría instancias de no prototipos (es decir, la versión original incorrecta 'void * (* Pop)()'. Su código es correcto y no tiene ese problema, pero usar '-Wstrict-prototypes' evitará que el problema vuelva a caer en el código. –

Cuestiones relacionadas