45

下面的代码可以编译,但 char 类型的行为与 int 类型的行为不同。

尤其

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

为三种类型生成 3 个模板实例:int8、uint8 和 char。是什么赋予了?

对于 int 而言,情况并非如此: int 和 uint32 导致相同的模板实例化,并签署了 int 另一个。

原因似乎是 C++ 将 char、signed char 和 unsigned char 视为三种不同的类型。而 int 与带符号的 int 相同。这是对的还是我错过了什么?

#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;

}

我正在使用 g++ 4.something

4

4 回答 4

68

这是您从标准中得到的答案:

3.9.1 基本类型[basic.fundamental]

声明为字符 ( char) 的对象应足够大以存储实现的基本字符集的任何成员。如果该集合中的字符存储在字符对象中,则该字符对象的整数值等于该字符的单个字符文字形式的值。char对象是否可以保存负值是实现定义的。字符可以显式声明unsignedsigned. Plain charsigned charunsigned char是三种不同的类型。 A char、 asigned char和 anunsigned char 占用相同的存储量并具有相同的对齐要求(basic.types); 也就是说,它们具有相同的对象表示。对于字符类型,对象表示的所有位都参与值表示。对于无符号字符类型,值表示的所有可能的位模式都表示数字。这些要求不适用于其他类型。在任何特定的实现中,普通对象可以采用与 a或 anchar相同的值;哪一个是实现定义的。signed charunsigned char

于 2009-01-12T18:58:48.243 回答
31

虽然大多数整数类型(例如short并且int默认为be )在 C++signedchar没有默认标志。

它既不是 typesigned char也不是unsigned char,所以实现可以决定它是否被签名。

这是 C++ 程序员在使用char8 位整数类型时遇到的常见错误。

于 2009-01-12T19:18:29.420 回答
27

对于诸如此类的问题,我喜欢查看 C 的基本原理文档,该文档通常也提供 C++ 奥秘的答案,这些奥秘有时会在我阅读标准时出现。它有这样的说法:

指定了三种类型的 char:signed、plain 和 unsigned。一个普通的 char 可以表示为有符号或无符号,这取决于实现,如在先前的实践中一样。引入有符号字符类型是为了在那些将普通字符实现为无符号的系统上提供单字节有符号整数类型。出于对称的原因,关键字signed 被允许作为其他整数类型的类型名称的一部分。

C 的基本原理

于 2009-01-12T20:01:42.470 回答
19

这是正确的, char,unsigned char并且signed char是单独的类型。char如果只是同义词signed charunsigned char取决于您的编译器实现,那可能会很好,但标准说它们是单独的类型。

于 2009-01-12T18:51:10.567 回答