2012-06-24 14 views
5

Teniendo en cuenta este código con 3 diferentes semántica llamada de función:llamada de función con diferentes semántica

void f(void){ 
    puts("OK"); 
} 

int main(void){ 
    f(); 
    (*f)(); 
    (&f)(); 

    return 0; 
} 

El primero es la manera estándar para llamar a f,

la segunda es la semántica para eliminación de referencias punteros de función,

pero en el tercero estoy aplicando el operador & al nombre de la función y parece funcionar bien.

¿Qué sucede en el segundo y tercer caso?

Gracias.

+1

El puntero a la función obtiene dereferenced para la llamada en el tercero. –

+5

Por diversión intente '(********** f)();' también – Flexo

+0

Pregunto en qué caso alguien debería usar la segunda y la tercera llamada ... –

Respuesta

8

Las llamadas a funciones son siempre realizadas a través de punteros a funciones. De C99 sección 6.5.2.2:

La expresión que denota la función llamada tendrá un puntero de tipo para funcionar.

Sin embargo, en casi todos los casos, un tipo de función decae a un tipo de puntero a función. Desde la sección de C99 6.3.2.1:

Excepto cuando es la operando del operador sizeof o la unario & operador, un designador de función con tipo "función que devuelve tipo" se convierte en una expresión que tiene escriba "puntero a función que devuelve tipo".

Así que sus tres llamadas se evalúan así:

(&f)(); 
(&(*(&f)))(); 
(&f)(); 

Todos son válidos. Pero, obviamente, el primero (f()) es el más limpio y fácil de leer.

+0

¿por qué no? (& (& f)()) válido. ¿Cuándo & f decae a tipo de puntero a función? – Raulp

+0

@softy: '& f' es ** ya ** un tipo de puntero a función. Entonces '&& f' es un tipo de puntero-puntero-función. –

+6

@OliCharlesworth - Solo que '& f' es un valor r, por lo que no puede ser el argumento de otro' & 'operador unario. – rodrigo

1

En el segundo caso, está utilizando un puntero a la función. Los punteros de función se utilizan para memorizar una referencia a una función, y poder llamarla a otra parte en su llamada. Por lo general, se utilizan para implementar devoluciones de llamadas. Entonces, si tiene un puntero a una función, debe usar la primera notación.

Creo que la primera y la tercera son equivalentes. De hecho, si se declara un puntero de función puede inicializar las dos siguientes maneras: los

void AFunction(); 
void (*funcPtr)() = NULL; 

funcPtr = AFunction; 
funcPtr = &AFunction; 
Cuestiones relacionadas