Question

Le code ci-dessous est compilé, mais le comportement du type char est différent de celui des types int.

En particulier

   cout << getIsTrue< isX<int8>::ikIsX  >() << endl;
   cout << getIsTrue< isX<uint8>::ikIsX  >() << endl;
   cout << getIsTrue< isX<char>::ikIsX  >() << endl;

résulte en 3 instanciations de modèles pour trois types: int8, uint8 et char. Qu'est-ce qui donne?

Il n'en va pas de même pour ints: int et uint32, qui entraînent la même instanciation du modèle et sont signés par un autre.

La raison semble être que C ++ considère char, sign char et unsigned char comme trois types différents. Alors que int est identique à un int signé. Est-ce vrai ou est-ce que je manque quelque chose?

#include <iostream>

using namespace std;

typedef   signed char       int8;
typedef unsigned char      uint8;
typedef   signed short      int16;
typedef unsigned short     uint16;
typedef   signed int        int32;
typedef unsigned int       uint32;
typedef   signed long long  int64;
typedef unsigned long long uint64;

struct TrueType {};
struct FalseType {};

template <typename T>
struct isX
{
   typedef typename T::ikIsX ikIsX;
};


// This  int==int32 is ambiguous
//template <>            struct isX<int  >    { typedef FalseType ikIsX; };  // Fails
template <>            struct isX<int32  >  { typedef FalseType ikIsX; };
template <>            struct isX<uint32 >  { typedef FalseType ikIsX; };


// Whay isn't this ambiguous? char==int8
template <>            struct isX<char  >  { typedef FalseType ikIsX; };
template <>            struct isX<int8  >  { typedef FalseType ikIsX; };
template <>            struct isX<uint8 >  { typedef FalseType ikIsX; };


template <typename T> bool getIsTrue();
template <>           bool getIsTrue<TrueType>() { return true; }
template <>           bool getIsTrue<FalseType>() { return false; }

int main(int, char **t )
{
   cout << sizeof(int8) << endl;  // 1
   cout << sizeof(uint8) << endl; // 1
   cout << sizeof(char) << endl;  // 1

   cout << getIsTrue< isX<int8>::ikIsX  >() << endl;
   cout << getIsTrue< isX<uint8>::ikIsX  >() << endl;
   cout << getIsTrue< isX<char>::ikIsX  >() << endl;

   cout << getIsTrue< isX<int32>::ikIsX  >() << endl;
   cout << getIsTrue< isX<uint32>::ikIsX  >() << endl;
   cout << getIsTrue< isX<int>::ikIsX  >() << endl;

}

J'utilise g ++ 4. quelque chose

Était-ce utile?

La solution

Voici votre réponse à partir de la norme:

  

3.9.1 Types fondamentaux [basic.fundamental]

     

Les objets déclarés en tant que caractères ( char ) doivent être suffisamment grands pour stocker tout membre du jeu de caractères de base de la mise en oeuvre. Si un caractère de cet ensemble est stocké dans un objet caractère, la valeur intégrale de cet objet caractère est égale à la valeur de la forme littérale à caractère unique de ce caractère. L'implémentation est définie si un objet char peut contenir des valeurs négatives. Les caractères peuvent être explicitement déclarés unsigned ou signed . Plain caractère , caractère signé et caractère non signé sont trois types distincts. A char , un char signé et un charité non signé occupent la même quantité de mémoire et ont les mêmes exigences en matière d'alignement ( basic.types ); c'est-à-dire qu'ils ont la même représentation d'objet. Pour les types de caractère, tous les bits de la représentation d'objet participent à la représentation de valeur. Pour les types de caractères non signés, tous les modèles de bits possibles de la représentation de valeur représentent des nombres. Ces exigences ne sont pas valables pour les autres types. En tout particulier   Lors de la mise en œuvre, un objet char peut prendre les mêmes valeurs qu’un char signé ou un charité non signé ; lequel est défini par l'implémentation.

Autres conseils

Pour des questions comme celle-ci, j’aimerais examiner le document de justification pour C, qui fournit souvent aussi des réponses aux mystères de C ++, qui m’arrive parfois lorsque je lis la norme. Voici ce qu’il en dit:

  

Trois types de caractères sont spécifiés: signé, brut et non signé. Un caractère simple peut être représenté comme signé ou non signé, en fonction de la mise en œuvre, comme dans la pratique antérieure. Le type signé du caractère a été introduit pour rendre disponible un type entier signé sur un octet sur les systèmes qui implémentent le caractère brut en tant que non signé. Pour des raisons de symétrie, le mot-clé signé est autorisé dans le nom de type d'autres types d'intégrale.

Justification de C

Bien que la plupart des types intégraux tels que short et int soient signés , char n'a pas de valeur par défaut. signalisation en C ++.

C'est une erreur courante que rencontrent les programmeurs C ++ lorsqu'ils utilisent char en tant que type entier 8 bits.

c'est correct, char , char non signé et char signé sont des types séparés. Cela aurait probablement été bien si char était simplement synonyme de char signé ou de char non signé en fonction de l'implémentation de vos compilateurs, mais la norme dit ce sont des types séparés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top