I tipi di dati più piccoli devono essere utilizzati nel codice intermedio?

0

Spesso utilizzo tipi di dati più piccoli nelle strutture / classi quando è necessario per risparmiare sulla memoria. Li uso anche in rete / disco IO.

La mia domanda è se il codice intermedio che utilizza quegli oggetti con tipi di dati più piccoli, dovrebbe essere dello stesso tipo, o solo tipi semplici come int e tagliarli durante l'archiviazione. Ad esempio:

struct Object
{
  int16 health;
  int8 mana;
};

void function(int16 health, int8 mana)
{
  Object object;
  object.health = health;
  object.mana = mana;
}

o

void function(int health, int mana)
{
  Object object;
  object.health = static_cast<int16>(health); // Cutting int
  object.mana = static_cast<int8>(mana); // Cutting int
}
    
posta John Lock 31.05.2016 - 18:10
fonte

1 risposta

6

Stai facendo la domanda sbagliata.

La domanda giusta è "chi dovrebbe essere responsabile di garantire che i valori desiderati siano entro i limiti richiesti dal tipo di dati?"

Diamo un'occhiata ai tuoi casi:

void function1(int16_t health, int8_t mana)
{
  Object object;
  object.health = health;
  object.mana = mana;
}

void function2(int health, int mana)
{
  Object object;
  object.health = static_cast<int16_t>(health); // Cutting int
  object.mana = static_cast<int8_t>(mana); // Cutting int
}

L'interfaccia di function1 ha un requisito di dimensioni esplicito sui suoi tipi. È quindi responsabilità di tutti che chiama tale funzione per verificare che i valori che si desidera memorizzare rientrino nelle dimensioni specificate nell'interfaccia.

function2 ha invece un requisito di dimensioni implicito . Dice che ci vuole int s. Ma non è così; se passi valori al di fuori della dimensione del tipo di dati, invoca il comportamento definito dall'implementazione.

Per certi aspetti, function1 è migliore. Le dimensioni per i parametri sono esplicitamente indicate. Ma a causa delle regole di conversione di C ++, qualcosa ovviamente rotto come questo non causerà nemmeno un errore di compilazione:

function1(0xFFFFFFF, 23);

Questa è una conversione restringente, che è consentita. Richiama il comportamento definito dall'implementazione, che probabilmente non è quello che desideri.

Quindi, la vera domanda è ... che fai vuoi?

Se l'utente desidera impostare lo stato su più di 0x7FFF, che cosa dovrebbe fare il codice? Dovrebbe accettarlo silenziosamente e invocare un comportamento definito dall'implementazione? O dovrebbe provocare una condizione di errore, lanciare un'eccezione o terminare semplicemente?

Se vuoi fare qualsiasi di quest'ultimo, devi usare function2 (o meglio, una versione di controllo degli errori di function2 ). Usandolo, il requisito implicito dell'interfaccia può essere almeno verificato. Ciò rende possibile rintracciare il codice che vuole impostare il valore in modo improprio.

    
risposta data 31.05.2016 - 18:34
fonte

Leggi altre domande sui tag