2010-10-15 8 views
28

In C, ho bisogno di conoscere la dimensione di una struct, che contiene dei puntatori di funzione. Posso essere garantito che su tutte le piattaforme e architetture:Che cosa è garantito circa la dimensione di un puntatore a funzione?

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

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

risposta

29

Da C99 spec, paragrafo 6.2.5, punto 27:

Un puntatore a void devono avere la stessa rappresentazione ed allineamento requisiti come un puntatore a un tipo carattere. Allo stesso modo, i puntatori per le versioni qualificate o non vuote dei tipi compatibili devono avere la stessa rappresentazione e i requisiti di allineamento . Tutti i puntatori ai tipi di struttura devono avere la stessa rappresentazione e i requisiti di allineamento tra loro. Tutti i puntatori ai tipi di unione devono avere lo stesso identici requisiti di allineamento e di corrispondenza . I puntatori per altri tipi non devono avere la stessa rappresentazione o allineamento requisiti.

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 altro tipo e viceversa nuovo; il risultato deve confrontare lo uguale al puntatore originale.

che implica che un tipo di puntatore a funzione può contenere qualsiasi altro valore di 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.

14

No, no, no.

C non favorisce le architetture di Harvard con diverse dimensioni di puntatori di codice e di dati, poiché idealmente durante la programmazione di tale architettura si desidera memorizzare i dati nella memoria di programma (stringhe letterali e simili), e per farlo si bisogno di puntatori di oggetti nello 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 di funzione può essere lanciato su un altro tipo di puntatore di funzione [*] e viceversa senza cestinare il valore, nello stesso modo in cui è possibile eseguire il cast di qualsiasi puntatore dell'oggetto su void* e viceversa. 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.

+3

Più in generale: qualsiasi puntatore a funzione può essere convertito in qualsiasi altro tipo di puntatore a funzione e viceversa. (C99 6.3.2.3/8) – schot

+0

@schot: giusto, in tal caso sarebbe davvero perverso renderli di dimensioni diverse, poiché indipendentemente dalla dimensione tutti i tipi di puntatori a funzione devono rappresentare esattamente lo stesso insieme di valori. Vale a dire, l'indirizzo di ogni funzione, oltre a un puntatore nullo. –

+0

Ottima risposta. La mia domanda dell'altra giornata illustra potenziali insidie ​​qui: http://stackoverflow.com/questions/3889541/issue-with-null-pointers-on-harvard-architecture-platform – Vicky

7

In aggiunta alle altre risposte, Wikipedia dice questo:

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

Anche se puntatori a funzione in C e C++ possono essere implementati come semplici indirizzi, in modo che in genere sizeof(Fx)==sizeof(void *), membro i puntatori in C++ vengono spesso implementati come come "pointer grossi", in genere due o tre volte la dimensione di un semplice puntatore di funzione , in modo da deal con ereditarietà virtuale.

Un puntatore a funzione è un'astrazione. Finché i requisiti dello standard sono soddisfatti, tutto è possibile. Cioè se nel programma sono presenti meno di 256 funzioni, è possibile 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.

+4

Downvoter: Quello che ho scritto è sbagliato, perché ...? – Secure

+0

Non vedo come sia sbagliato. Questa è davvero una possibilità per un'implementazione legale di C, anche se sarei sorpreso se ci fosse un'implementazione che lo ha fatto. – nategoose

+3

Non era il mio downvote, ma la roulette del puntatore membro C++ è irrilevante poiché la domanda è su C. L'ultimo paragrafo è un punto perfettamente valido, tuttavia, i puntatori di funzione certamente * potrebbero * essere legalmente un indice in qualche tabella, con un extra livello di riferimento per chiamarli realmente. –

1

Esiste un esempio pratico di diverse dimensioni che erano comuni. Nella MS-DOS & nella programmazione iniziale di Windows C, nel modello di memoria "medio" erano presenti puntatori di dati a 16 bit ma puntatori di funzioni a 32 bit e il modello di memoria "compatto" era il contrario.

Problemi correlati