45

以下のコードはコンパイルされますが、char 型と int 型では動作が異なります。

特に

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

int8、uint8、および char の 3 つのタイプのテンプレートが 3 つインスタンス化されます。何を与える?

同じことは int には当てはまりません: int と uint32 は同じテンプレートのインスタンス化をもたらし、別の int を署名します。

その理由は、C++ が char、signed char、および unsigned char を 3 つの異なる型として認識しているためと思われます。一方、int は signed 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オブジェクトが負の値を保持できるかどうかは、実装によって定義されます。文字は明示的に宣言unsignedするか、またはにすることができますsignedプレーン、、、charおよびsigned charunsigned char3つの異なるタイプです。char、、、signed charおよびunsigned char は同じ量のストレージを占有し、同じ配置要件( basic.types )を持ちます); つまり、それらは同じオブジェクト表現を持っています。文字タイプの場合、オブジェクト表現のすべてのビットが値表現に参加します。符号なし文字タイプの場合、値表現のすべての可能なビットパターンは数値を表します。これらの要件は、他のタイプには当てはまりません。特定の実装では、プレーンオブジェクトはaまたは;charと同じ値を取ることができます。どちらが実装定義です。signed charunsigned char

于 2009-01-12T18:58:48.243 に答える
31

ほとんどの整数型は と のようshortintデフォルトでありますがsignedcharC++ にはデフォルトの標識がありません。

タイプsigned charでも でもないunsigned charため、署名されているかどうかは実装によって決定される場合があります。

charこれは、C++ プログラマーが8 ビット整数型として使用するときに遭遇するよくある間違いです。

于 2009-01-12T19:18:29.420 に答える
27

このような質問については、C の理論的根拠のドキュメントを参照するのが好きです。これは、標準を読んでいるときに時々発生する C++ の謎に対する回答も提供することがよくあります。それについて次のように述べています。

char には、signed、plain、unsigned の 3 種類が指定されています。通常の char は、以前の慣行と同様に、実装に応じて、符号付きまたは符号なしとして表すことができます。signed char 型は、プレーン char を unsigned として実装するシステムで 1 バイトの signed 整数型を使用できるようにするために導入されました。対称性の理由から、キーワード signed は、他の整数型の型名の一部として使用できます。

C の根拠

于 2009-01-12T20:01:42.470 に答える
19

それは正しい、、、charおよびunsigned char別個signed charのタイプです。コンパイラの実装のいずれかまたは依存charの同義語であるとしたら、おそらくそれは良かったでしょうが、標準では、それらは別々のタイプであるとされています。signed charunsigned char

于 2009-01-12T18:51:10.567 に答える