2010-07-05 14 views
6

En particular, será la siguiente vez no funciona como se esperaba:¿Es seguro llamar punteros a funciones fundidas?

typedef void(*func_p)(void*); 

void foo(int* data) 
    { 
    printf("%i\n",*data); 
    } 

int main(int argc, char** argv) 
    { 
    func_p bar; 
    int x = 42; 

    bar = foo; 
    bar((void*)&x); 

    return 0; 
    } 

es decir, que puede depender de punteros de datos (void*, int*, struct baz*, pero no neccesarily void(*)(void)) siempre que se pasa compatably?

+0

¿hay alguna manera de suscribirse a una pregunta para que se le notifique cuando se responda, sin dejar estos estúpidos comentarios y rastrearlo a través de ella? –

+0

@Gollum: haga clic en la estrella hueca. A continuación, verá los cambios en la pestaña 'favoritos' de su página de cambios recientes (haciendo clic en el sobre) – SLaks

+0

Gracias :) @SLaks, lo aprecio. –

Respuesta

7

La norma no exige que esto funcione. El estándar requiere que char* y void* tengan los mismos requisitos de representación y alineación, todos los punteros struct lo hacen y todos los punteros de unión lo hacen también. Si bien es un comportamiento indefinido para llamar al puntero de función emitida en cualquier caso (§6.5.2.2p9), los mismos requisitos de representación y alineación dan una garantía práctica de que la llamada funciona (§6.2.5p27).

No es necesario que otros tipos de punteros se comporten de esa manera, aunque no he conocido personalmente una máquina así. Es teóricamente posible que un int* tenga un sizeof menor que un char* por ejemplo (si int tiene requisitos de alineación más estrictos que char, esto podría ser una medida razonable). Según la convención de llamadas correcta, en una máquina así sería prácticamente imposible llamar a un puntero de función emitida.

+0

+1, aunque bastante decepcionante. –

+0

@David, francamente, si eso significa que necesitaría crear docenas de funciones de contenedor para poder pasar mi función como parámetro a ese tipo - simplemente lanzaría :) –

+0

@litb, lo he estado haciendo de esa manera durante un aunque exactamente por esa razón:] –

1

A menos que su código se dirija a mainframes antiguos raros, para todos los fines prácticos funcionará bien. Ninguna máquina moderna usa representaciones diferentes para diferentes tipos de punteros, y no creo que sea realista que alguna máquina futura lo haga. Es simplemente ilógico y al revés, muy parecido a los complementos: la aritmética complementaria.

Si todavía está preocupado o quiere satisfacer a los puristas del idioma, siga la sugerencia de caf.

+0

Tenía la impresión de que los punteros a las funciones pueden tener un tamaño diferente al de los punteros a los datos, ¿o es algo de C++? – kibibu

+0

Es algo de Windows de 16 bits relacionado con la idea de Microsoft de "modelo de memoria" y punteros cercanos/lejanos. Para aclarar: el estándar ** les permite ** ser diferentes, pero no hay ninguna razón por la que alguna vez deberían ser diferentes en una arquitectura moderna. –

+0

@kibibu @R .. en realidad, tener punteros de función más grandes que los punteros de datos es bastante común en los microcontroladores y similares, ya que la memoria del programa puede estar separada de la memoria de datos y/o no escribible. –

Cuestiones relacionadas