2011-06-09 23 views
18

Por ejemplo:En C, ¿cuál es la diferencia entre `& function` y` function` cuando se pasa como argumentos?

#include <stdio.h> 

typedef void (* proto_1)(); 
typedef void proto_2(); 

void my_function(int j){ 
    printf("hello from function. I got %d.\n",j); 
} 

void call_arg_1(proto_1 arg){ 
    arg(5); 
} 
void call_arg_2(proto_2 arg){ 
    arg(5); 
} 
void main(){ 
    call_arg_1(&my_function); 
    call_arg_1(my_function); 
    call_arg_2(&my_function); 
    call_arg_2(my_function); 
} 

La ejecución de este me sale el siguiente:

> tcc -run try.c 
hello from function. I got 5. 
hello from function. I got 5. 
hello from function. I got 5. 
hello from function. I got 5. 

Mis dos preguntas son:

  • ¿Cuál es la diferencia entre un prototipo de función definida con (* proto) y uno definido sin?
  • ¿Cuál es la diferencia entre llamar a una función con el operador de referencia (&) y sin?
+1

No creo que haya una diferencia. No publicando como respuesta porque no estoy realmente seguro. – JAB

+0

posible duplicado de [Punteros de función en el operador de dirección C "innecesario"] (http://stackoverflow.com/questions/258422/function-pointers-in-c-address-operator-unnecessary) – outis

Respuesta

18

No hay diferencia. Para evidencia ver el C99 specification (sección 6.7.5.3.8).

"La declaración de un parámetro como '' función que devuelve el tipo '' se ajustará a '' el apuntador a función que devuelve el tipo '', como en 6.3.2.1."

+0

+1 para referencia a la especificación – groovingandi

+0

Gracias por la referencia Nick! (Por cierto, es la sección 6.7. ** 5 **. 3.8.) ¿Es esencialmente un caso especial de lenguaje? – brice

+0

@brice - gracias, he editado. Sí, un caso especial. El puntero a la función tiene más sentido para ser coherente con el resto del lenguaje, pero supongo que agregaron el otro caso para legibilidad –

7

no hay ninguna diferencia entre &function y function cuando se pasa como argumento

Sin embargo, existe una diferencia entre sus typedefs. No sé la explicación oficial, es decir, ¿qué es exactamente la diferencia, pero de lo que recuerdo

typedef void (*name1)(void); 

y

typedef void(name2)(void); 

son diferentes:

nombre1 es un puntero a una función que toma no paramter y no devuelve nada

name2 es una función que no toma ningún parámetro y no devuelve nada

puede comprobarlo mediante la compilación:

typedef void (*pointer)(void); 
typedef void (function)(void); 

void foo(void){} 

int main() 
{ 
    pointer p; 
    function f; 

    p = foo; //compiles 
    p(); 

    f = foo; //does not compile 
    f(); 
} 

de nuevo, no soy la persona adecuada para explicar la razón exacta de este comportamiento, pero yo creo que si se echa un vistazo a las normas se encuentra la explicación en algún lugar hay

+1

Supongo que ya podría sentir este viene: * ... al pasar como argumento * - ¿cuál es la diferencia de lo contrario, entonces? :-) –

+0

jeje :) no estoy seguro, pero por lo que sé totalmente lo mismo. ¿por qué ambos existen? no lo sé. creo que es como int & const r; y int & r; de C++ –

+0

Gracias por la aclaración sobre el typedefs. Eso tiene sentido y sigue la semántica habitual. – brice

5

No hay diferencia entre la función y la función &; ambas son direcciones. Puede ver esto imprimiendo ambos:

function bar(); 

.... 
printf("addr bar is 0x%d\n", &bar); 
printf("bar is 0x%d\n", bar); 
+2

Su respuesta es correcta, pero el "usted puede ver esto por ..." es incorrecto. Para una matriz, 'array' y' & array' no son remotamente iguales (tienen * muy * tipos diferentes) pero imprimir sus direcciones con 'printf' mostrará lo mismo (suponiendo que use'% p' correctamente en lugar de '% d' y emitido a' void * '). Por cierto, no hay forma de imprimir punteros de función con 'printf' ya que C carece completamente de cualquier conversión de un tipo de puntero a' void * 'o cualquier tipo de entero. –

+0

La afirmación "no hay forma de imprimir punteros a las funciones" no es verdadera. Puede ejecutar el código que pegué en la parte superior (lo hice). –

+2

Ese código invoca un comportamiento indefinido al pasar los tipos que no coinciden a 'printf'. Si hace lo que esperaba, eso significa que tuvo mala suerte, es decir, no se detectó el error en su código. –

2

La diferencia es solo estilística. Tiene el mismo escenario, cuando el uso de punteros de función:

void func (void); 

...

void(*func_ptr)(void) = func; 

func_ptr(); // call func 
(*func_ptr)(); // call func 

printf("%d\n", ptr); 
printf("%d\n", *ptr); 

Hay algunos que dicen que el (* func_ptr)() sintaxis es preferir, para que quede claro que la llamada a la función se realiza a través de un puntero de función. Otros creen que el estilo con * es más claro.

Como es habitual, es probable que no haya estudios científicos que demuestren que ninguna forma es mejor que la otra, así que elija un estilo y apéguese a él.

Cuestiones relacionadas