2009-08-04 6 views
3

Je me demande s'il est nécessaire de réinterpréter_cast dans la fonction ci-dessous. ITER_T pourrait être un char *, char non signé *, std :: vector < non signé char > itérateur, ou autre chose comme ça. Cela ne semble pas faire de mal jusqu'ici, mais est-ce que le casting affecte la façon dont les octets sont copiés?réinterpréter la conversion vers et à partir de char * et char non signé *

template<class ITER_T> 
char *copy_binary(
    unsigned char length, 
    const ITER_T& begin) 
{ 
    // alloc_storage() returns a char* 
    unsigned char* stg = reinterpret_cast<unsigned char*>(alloc_storage(length)); 
    std::copy(begin, begin + length, stg); 
    return reinterpret_cast<char*>(stg); 
} 
+2

De quel type la fonction alloc_storage retourne-t-elle? – zdan

Répondre

6

reinterpret_casts sont utilisés pour les distributions définies par l'implémentation de bas niveau. Selon la norme, reinterpret_casts peut être utilisé pour les transformations suivantes (C++ 03 05/02/10):

  • pointeur vers un type intégral
  • type intégral à pointeur
  • Un pointeur vers une fonction peut être converti en un pointeur vers une fonction d'un type différent
  • un pointeur vers un objet peut être converti en un pointeur vers un objet de type différent
  • pointeur sur les fonctions membres ou pointeur vers les membres de données peuvent être converties en fonctions ou objets d'un type différent. Le résultat d'une telle conversion de pointeur n'est pas spécifié, à l'exception du pointeur a reconverti en son type d'origine.
  • Une expression de type A peut être convertie en une référence au type B si un pointeur vers le type A peut être explicitement converti en type B en utilisant reinterpret_cast.

Cela dit, en utilisant le reinterpret_cast n'est pas une bonne solution dans votre cas, puisque la coulée à différents types ne sont pas spécifiés par la norme, bien que la coulée char *-unsigned char * et retour devrait fonctionner sur la plupart des machines.

Dans votre cas, je pense à utiliser un static_cast ou non coulée tout en définissant stg que le type char *:

template<class ITER_T> 
char *copy_binary(
    unsigned char length, 
    const ITER_T& begin) 
{ 
    // alloc_storage() returns a char* 
    char* stg = alloc_storage(length); 
    std::copy(begin, begin + length, stg); 
    return stg; 
} 
+0

+1 Cela me semble une bonne réponse - il vous indique quand utiliser reinterpret_cast et que vous ne devriez pas l'utiliser ici. –

+2

Tout va bien sauf la partie sur l'utilisation de 'static_cast'. Ma compréhension est que cast statique ne peut être utilisé pour convertir entre les types de pointeurs liés et «void *». 'char non signé' et 'char' sont des types non liés selon la norme et donc ce cas est seulement couvert par la 4ème balle dans reinterpret_cast. –

1

Le code comme écrit fonctionne comme prévu selon la norme 4.7 (2), bien que ceci est garanti uniquement pour les machines avec une représentation en complément à deux. Si alloc_storage renvoie un caractère *, et 'char' est signé, si je comprends bien 4.7 (3), le résultat serait défini par l'implémentation si le type de valeur de l'itérateur est non signé et que vous laisser tomber le cast et passer le char * à copier.

0

Donc, si je comprends bien, la conversion en caractère non signé doit garantir une copie octet par octet non signée. Mais ensuite vous le rejetez pour le retour. La fonction semble un peu douteuse, quel est exactement le contexte/la raison de la configuration de cette façon? Une solution rapide pourrait être de remplacer tout cela par un memcpy() (mais comme commenté, ne l'utilisez pas sur les objets itérateur) - sinon, supprimez simplement les conversions redondantes.

+1

Vous devriez faire attention en utilisant memcpy avec les itérateurs. Dans ce cas, il utilise un vecteur, mais les données contenues ne sont pas toujours contiguës. –

+0

Oh oui, vous avez absolument raison. – nielsj

+0

Voici le contexte: Je travaille avec une classe StringSlice qui conserve un char * et la plage de sous-chaînes. Cependant, certaines des données que je garde dans le StringSlice devraient vraiment être interprétées comme non signées. La classe qui a le membre StringSlice permet à quelqu'un de définir les données avec des chars unsigned ou char signés de plusieurs manières, et il existe des méthodes pour récupérer les données en tant que StringSlice, un char non signé *, ou copier les données en tant que char non signés –

1

La réponse courte est oui, cela pourrait affecter.

omble et omble non signés sont des types convertibles (3.9.1 en C++ standard 0x N2800) de sorte que vous pouvez attribuer un à l'autre. Vous n'avez pas besoin du casting.

[3.9.1] ...Un char, un caractère signé et un caractère non signé occupent la même quantité de stockage et ont les mêmes exigences d'alignement ; c'est-à-dire, ils ont la même représentation d'objet.


[4,7] ...

Si le type de destination est non signé, la valeur résultante est le entier moins unsigned congru à le nombre entier de source (modulo 2n où n est le nombre de bits utilisés pour représentent le type non signé).

[Note: Dans deux de la représentation du complément, cette conversion est conceptuelle et il n'y a aucun changement dans la configuration binaire (s'il n'y a pas troncature). -fin noter ]

Si le type de destination est signé, la valeur est inchangée si elle peut être représenté dans le type de destination (et la largeur du champ de bits); sinon, la valeur est définie par l'implémentation.

Par conséquent, même dans le pire des cas, vous obtiendrez la meilleure conversion (moins implémentée). Quoi qu'il en soit, dans la plupart des implémentations, cela ne changera rien dans le modèle binaire, et vous n'aurez même pas de conversion si vous regardez dans l'assembleur généré.

template<class ITER_T> 
char *copy_binary(unsigned char length, const ITER_T& begin) 
{ 
    char* stg = alloc_storage(length); 
    std::copy(begin, begin + length, stg); 
    return stg; 
} 

reinterpret_cast vous dépendez Utilisez-le compilateur:

[5.2.10.3] La cartographie réalisée par reinterpret_cast est mise en œuvre défini. [Note: il pourrait, ou ne pourrait pas, produire une représentation différente de la valeur d'origine . -end note]

Remarque: This est un article associé intéressant.

Questions connexes