Cosa è garantito circa la dimensione di un puntatore a funzione?

In C, ho bisogno di conoscere la dimensione di una struct, che ha dei puntatori di funzione in essa. Posso essere garantito che su tutte le piattaforms e architetture:

  • la dimensione di un vuoto * ha le stesse dimensioni di un puntatore a funzione?
  • la dimensione del puntatore della funzione non differisce a causa del suo tipo di ritorno?
  • la dimensione del puntatore della funzione non differisce a causa dei suoi tipi di parametri?

Presumo che la risposta sia sì a tutti questi, ma voglio essere sicuro. Per contesto, sto chiamando sizeof(struct mystruct) e nient’altro.

Dalla specifica C99, sezione 6.2.5, paragrafo 27:

Un puntatore a vuoto deve avere gli stessi requisiti di rappresentazione e allineamento di un puntatore a un tipo di carattere. Analogamente, i riferimenti a versioni qualificate o non qualificate di tipi compatibili devono avere gli stessi requisiti di rappresentazione e allineamento. Tutti i puntatori ai tipi di strutture devono avere gli stessi requisiti di rappresentazione e allineamento reciproci. Tutti i puntatori ai tipi di unione devono avere gli stessi requisiti di rappresentazione e allineamento reciproci. I puntatori ad altri tipi non devono avere la stessa rappresentazione o requisiti di allineamento.

Quindi no; nessuna garanzia che un void * possa contenere un puntatore a funzione.

E sezione 6.3.2.3, paragrafo 8:

Un puntatore a una funzione di un tipo può essere convertito in un puntatore a una funzione di un altro tipo e viceversa; il risultato deve essere uguale al puntatore originale.

implicando che un tipo di puntatore a funzione può contenere qualsiasi altro valore del puntatore di funzione. Tecnicamente, ciò non equivale a garantire che i tipi di puntatore a funzione non possano variare di dimensioni, ma semplicemente che i loro valori occupino lo stesso intervallo l’uno dell’altro.

No, no, no.

C non favorisce le architetture di Harvard con differenti dimensioni di puntatori di codice e di dati, perché idealmente quando si programma per una tale architettura si desidera memorizzare i dati nella memoria di programma (stringhe letterali e simili), e per fare ciò occorrono puntatori di oggetti in lo spazio del codice. Ma non le proibisce, quindi per quanto riguarda lo standard, i puntatori di funzione possono fare riferimento a uno spazio di indirizzi che ha una dimensione diversa dallo spazio di indirizzamento dei dati.

Tuttavia, qualsiasi puntatore a funzione può essere lanciato su un altro tipo di puntatore a funzione [*] e viceversa senza cestinare il valore, nello stesso modo in cui qualsiasi puntatore a object può essere lanciato su void* e back. Quindi sarebbe piuttosto sorprendente per i puntatori di funzioni variare di dimensioni in base alla loro firma. Non c’è un “uso” ovvio per lo spazio extra, se devi essere in grado di archiviare lo stesso valore in meno spazio e recuperarlo al momento del ritorno.

[*] Grazie, schot.

In aggiunta alle altre risposte, Wikipedia dice questo:

http://en.wikipedia.org/wiki/Function_pointer

Sebbene i puntatori di funzione in C e C ++ possano essere implementati come indirizzi semplici, così che tipicamente sizeof(Fx)==sizeof(void *) , i puntatori membri in C ++ sono spesso implementati come “pointer grossi”, tipicamente due o tre volte la dimensione di un semplice puntatore a funzione, per gestire l’ereditarietà virtuale.

Un puntatore a funzione è un’astrazione. Finché i requisiti dello standard sono soddisfatti, tutto è ansible. Ad esempio, se nel programma sono presenti meno di 256 funzioni, è ansible implementare i puntatori di funzione utilizzando un singolo byte con il valore 0 per NULL e i valori da 1 a 255 come indice in una tabella con gli indirizzi fisici. Se superi le 255 funzioni, potrebbe essere esteso per utilizzare 2 byte.

C’è un esempio pratico di diverse dimensioni che erano comuni. Nella MS-DOS e nella programmazione iniziale di Windows C, nel modello di memoria “medio” si disponevano di puntatori di dati a 16 bit ma puntatori di funzioni a 32 bit e il modello di memoria “compatto” era il contrario.