2009-04-05 11 views
8

Qualcuno può indicarmi l'implementazione dell'operatore sizeof in C++ e anche qualche descrizione sulla sua implementazione.Come viene implementato l'operatore sizeof in C++?

sizeof è uno degli operatori che non può essere sovraccaricato.

Quindi significa che non possiamo modificare il suo comportamento predefinito?

+3

quanto possibile utilizzo si potrebbe avere per un tale scenario? – Mikeage

+2

Wow, pensa al danno che potresti causare sovraccaricando sizeof :-) – paxdiablo

+0

la mia intenzione è solo quella di esaminare l'implementazione interna dell'operatore sizeof. – anand

risposta

22

sizeof non è un vero operatore in C++. È solo una sintassi speciale che inserisce una costante uguale alla dimensione dell'argomento. sizeof non necessita o non ha alcun supporto di runtime.

Modifica: vuoi sapere come determinare la dimensione di una classe/struttura guardando la sua definizione? Le regole per questo fanno parte dello ABI e i compilatori si limitano a implementarle. Fondamentalmente le regole consistono in

  1. definizioni di dimensioni e allineamento per tipi primitivi;
  2. struttura, dimensione e allineamento dei vari puntatori;
  3. regole per il confezionamento di campi in strutture;
  4. regole relative alle cose relative alla tabella virtuale (più esoteriche).

Tuttavia, ABI sono piattaforma e spesso specifico del fornitore, cioè su x86 e (diciamo) IA64 la dimensione di A seguito sarà diverso perché IA64 non consente l'accesso ai dati non allineati.

struct A 
{ 
    char i ; 
    int j ; 
} ; 

assert (sizeof (A) == 5) ; // x86, MSVC#pragma pack(1) 
assert (sizeof (A) == 8) ; // x86, MSVC default 
assert (sizeof (A) == 16) ; // IA64 
+0

Quindi come calcola il valore costante, cioè la dimensione della variabile? – anand

+1

Alien01, non calcola la dimensione della variabile. sizeof() è stato risolto ("eseguito", se lo si desidera) in * tempo di compilazione *. Il compilatore inserirà il valore corretto, che conosce già. Ad esempio, su un'architettura x86 a 32 bit, saprà che gli int sono lunghi 32 bit, i puntatori sono 32 bit, ecc. –

+1

Alien01: ho aggiunto un riferimento su come il * compiler * calcola le dimensioni della struttura. Al momento dell'esecuzione, le dimensioni della struttura sono fisse e conosciute, come quando si scrive 'int i = 8;' in realtà nessuno * calcola * 8 in fase di esecuzione. –

14

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

Fondamentalmente, per citare Bjarne Stroustrup's C++ FAQ:

Sizeof non può essere sovraccaricato perché le operazioni incorporati, come ad esempio incrementando un puntatore in un array dipende implicitamente su di esso. Si consideri:

X a[10]; 
X* p = &a[3]; 
X* q = &a[3]; 
p++; // p points to a[4] 
    // thus the integer value of p must be 
    // sizeof(X) larger than the integer value of q 

Così, sizeof (X) non poteva essere dato un nuovo e diverso significato dal programmatore senza violare regole linguistiche di base.

+0

Non fornisce dettagli di implementazione. La definizione esatta della funzione potrebbe essere l'opzione migliore. – anand

+0

sizeof non può essere una funzione perché accetta sia tipi che valori: confronta sizeof (int) e sizeof ("123"). –

+0

Anton, potrebbe essere un modello e accettare un tipo molto bene –

7

No, non è possibile cambiarlo. Cosa speri di imparare vedendo una sua implementazione?

Ciò che sizeof non può essere scritto in C++ utilizzando più operazioni di base. Non è una funzione, o parte di un'intestazione di libreria come ad es. printf o malloc. È dentro il compilatore.

Edit: Se il compilatore è di per sé scritto in C o C++, allora si può pensare di realizzazione essere qualcosa di simile:

size_t calculate_sizeof(expression_or_type) 
{ 
    if (is_type(expression_or_type)) 
    { 
     if (is_array_type(expression_or_type)) 
     { 
      return array_size(exprssoin_or_type) * 
      calculate_sizeof(underlying_type_of_array(expression_or_type)); 
     } 
     else 
     { 
      switch (expression_or_type) 
      { 
       case int_type: 
       case unsigned_int_type: 
        return 4; //for example 
       case char_type: 
       case unsigned_char_type: 
       case signed_char_type: 
        return 1; 
       case pointer_type: 
        return 4; //for example 

       //etc., for all the built-in types 
       case class_or_struct_type: 
       { 
        int base_size = compiler_overhead(expression_or_type); 
        for (/*loop over each class member*/) 
        { 
          base_size += calculate_sizeof(class_member) + 
           padding(class_member); 
        } 
        return round_up_to_multiple(base_size, 
           alignment_of_type(expression_or_type)); 
       } 
       case union_type: 
       { 
        int max_size = 0; 
        for (/*loop over each class member*/) 
        { 
          max_size = max(max_size, 
          calculate_sizeof(class_member)); 
        } 
        return round_up_to_multiple(max_size, 
          alignment_of_type(expression_or_type)); 
       } 
      } 
     } 
    } 
    else 
    { 
     return calculate_sizeof(type_of(expression_or_type)); 
    } 
} 

Si noti che è è molto pseudo-codice. Ci sono molte cose che non ho incluso, ma questa è l'idea generale. Il compilatore probabilmente non lo fa in realtà.Probabilmente calcola la dimensione di un tipo (inclusa una classe) e la memorizza, invece di ricalcolare ogni volta che scrivi sizeof(X). È anche permesso ad es. i puntatori sono di dimensioni diverse a seconda di cosa indicano.

+0

"Che cosa speri di imparare vedendo una sua implementazione?" Non sembra una risposta valida. – anand

+0

So che è una schivata, ma potresti essere effettivamente interessato a qualche problema correlato che ha una risposta più facile ... – Doug

5

sizeof fa ciò che fa al momento della compilazione. I sovraccarichi dell'operatore sono semplicemente funzioni e fanno ciò che fanno in fase di esecuzione. Non è quindi possibile sovraccaricare sizeof, anche se lo standard C++ lo ha consentito.

3

sizeof è un operatore in fase di compilazione, il che significa che viene valutato in fase di compilazione.

Non può essere sovraccaricato, perché ha già un significato su tutti i tipi definiti dall'utente - la sizeof() una classe è la dimensione che l'oggetto definito dalla classe prende in memoria, e la dimensione di (dimensione dell'oggetto che i nomi delle variabili occupano nella memoria.

-1

Dai un'occhiata all'origine per il Gnu C++ compiler per un mondo reale su come è fatto.

1

A meno che non sia necessario vedere come vengono calcolate le dimensioni specifiche di C++ (ad esempio l'allocazione per la tabella v), è possibile consultare il compilatore C di Plan9. È molto più semplice che provare ad affrontare g ++.

1

variabile:

#define getsize_var(x) ((char *)(&(x) + 1) - (char *)&(x)) 

Tipo:

#define getsize_type(type) ((char*)((type*)(1) + 1) - (char*)((type *)(1)))