0

Cygwin gcc 4.5.3

C++ のさまざまな計算で使用される中間結果を特定しようとしています。「char」の場合、次の結果が得られます (x は char です)。

x op y is of type char if y is a char/unsigned char
x op y is of type y otherwise except if op is left/right shift

左/右シフトの場合、中間結果は「int」型になり、他のすべての計算とは逆になります。これは標準実装ですか?

使用したコードは次のとおりです (あまり興奮しないでください)。

# include <iostream>
# include <iomanip>
# include <typeinfo>
# include "cstdio"
# include <cstdlib>

using namespace std;

typedef unsigned char  UCHAR;
typedef unsigned short USHORT;
typedef unsigned int   INT;
typedef unsigned long  ULONG;
string find(type_info* info) {
   struct type {
      type_info* typeInfo;
      string     name;
   };
   int i;
   static type types[] = { {const_cast<type_info*>(&typeid(bool)),   " BOOL"  }
                         , {const_cast<type_info*>(&typeid(char)),   " CHAR"  }
                         , {const_cast<type_info*>(&typeid(UCHAR)),  " UCHAR" }
                         , {const_cast<type_info*>(&typeid(short)),  " SHORT" }
                         , {const_cast<type_info*>(&typeid(USHORT)), " USHORT"}
                         , {const_cast<type_info*>(&typeid(int)),    " INT"   }
                         , {const_cast<type_info*>(&typeid(uint)),   " UINT"  }
                         , {const_cast<type_info*>(&typeid(long)),   " LONG"  }
                         , {const_cast<type_info*>(&typeid(ULONG)),  " ULONG" }
                         };
   for(i = 0; i < sizeof(types)/sizeof(types[0]); i++ )
      if (types[i].typeInfo == info) break;
   if (i >= sizeof(types)/sizeof(types[0])) return " NOT FOUND";
   return types[i].name;
}
void func0(char x) {
   ios_base::fmtflags ioFlags = cout.flags();
   string info = find(const_cast<type_info*>(&typeid(x)));
   char save = x;
   cout << "func0(char " << (long)x << ')' << endl;
   cout << "!x  " << setw(12) << (!x)    << " 0x" << setw(8) << setfill('0') << hex << (!x) <<  find(const_cast<type_info*>(&typeid(!x))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "~x  " << setw(12) << (~x)    << " 0x" << setw(8) << setfill('0') << hex << (~x) <<  find(const_cast<type_info*>(&typeid(~x))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "+x  " << setw(12) << (+x)    << " 0x" << setw(8) << setfill('0') << hex << (+x) <<  find(const_cast<type_info*>(&typeid(+x))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "-x  " << setw(12) << (-x)    << " 0x" << setw(8) << setfill('0') << hex << (-x) <<  find(const_cast<type_info*>(&typeid(-x))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "++x " << setw(12) << (long)(++x)    << " 0x" << setw(8) << setfill('0') << hex << (++x) <<  find(const_cast<type_info*>(&typeid(++x))) << endl;
   cout.flags(ioFlags); cout << setfill(' '); x = save;
   cout << "--x " << setw(12) << (long)(--x)    << " 0x" << setw(8) << setfill('0') << hex << (--x) <<  find(const_cast<type_info*>(&typeid(--x))) << endl;
   cout.flags(ioFlags); cout << setfill(' '); x = save;
   cout << "x++ " << setw(12) << (long)(x++)    << " 0x" << setw(8) << setfill('0') << hex << (x++) <<  find(const_cast<type_info*>(&typeid(x++))) << endl;
   cout.flags(ioFlags); cout << setfill(' '); x = save;
   cout << "x-- " << setw(12) << (long)(x--)    << " 0x" << setw(8) << setfill('0') << hex << (x--) <<  find(const_cast<type_info*>(&typeid(x--))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << endl;

}
void func1(char x, char y) {
   ios_base::fmtflags ioFlags = cout.flags();
   cout << "func1(char " << (signed long)x << ", char " << (unsigned long)y << ')' << endl;
   cout << "x  + y " << setw(12) << (x  + y) << " 0x" << setw(8) << setfill('0') << hex << (x  + y) <<  find(const_cast<type_info*>(&typeid(x + y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  - y " << setw(12) << (x  - y) << " 0x" << setw(8) << setfill('0') << hex << (x  - y) <<  find(const_cast<type_info*>(&typeid(x - y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  * y " << setw(12) << (x  * y) << " 0x" << setw(8) << setfill('0') << hex << (x  * y) <<  find(const_cast<type_info*>(&typeid(x * y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   if (y == 0) {
        cout << "x  / y " << x << " / 0" <<  endl;
   } else {
        cout << "x  / y " << setw(12) << (x  / y) << " 0x" << setw(8) << setfill('0') << hex << (x / y) <<  find(const_cast<type_info*>(&typeid(x / y))) << endl;
   }
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x %  y " << setw(12) << (x  & y) << " 0x" << setw(8) << setfill('0') << hex << (x  & y) <<  find(const_cast<type_info*>(&typeid(x  & y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x << y " << setw(12) << (x << y) << " 0x" << setw(8) << setfill('0') << hex << (x << y) <<  find(const_cast<type_info*>(&typeid(x << y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x >> y " << setw(12) << (x >> y) << " 0x" << setw(8) << setfill('0') << hex << (x >> y) <<  find(const_cast<type_info*>(&typeid(x >> y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  & y " << setw(12) << (x  & y) << " 0x" << setw(8) << setfill('0') << hex << (x  & y) <<  find(const_cast<type_info*>(&typeid(x  & y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  | y " << setw(12) << (x  | y) << " 0x" << setw(8) << setfill('0') << hex << (x  | y) <<  find(const_cast<type_info*>(&typeid(x  | y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  ^ x " << setw(12) << (x  ^ y) << " 0x" << setw(8) << setfill('0') << hex << (x  ^ y) <<  find(const_cast<type_info*>(&typeid(x  ^ y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << endl;
}
void func1(char x, unsigned char y) {
   ios_base::fmtflags ioFlags = cout.flags();
   cout << "func1(char " << (signed long)x << ", uchar " << (unsigned long)y << ')' << endl;
   cout << "x  + y " << setw(12) << (x  + y) << " 0x" << setw(8) << setfill('0') << hex << (x  + y) <<  find(const_cast<type_info*>(&typeid(x + y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  - y " << setw(12) << (x  - y) << " 0x" << setw(8) << setfill('0') << hex << (x  - y) <<  find(const_cast<type_info*>(&typeid(x - y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  * y " << setw(12) << (x  * y) << " 0x" << setw(8) << setfill('0') << hex << (x  * y) <<  find(const_cast<type_info*>(&typeid(x * y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   if (y == 0) {
        cout << "x  / y " << x << " / 0" <<  endl;
   } else {
        cout << "x  / y " << setw(12) << (x  / y) << " 0x" << setw(8) << setfill('0') << hex << (x / y) <<  find(const_cast<type_info*>(&typeid(x / y))) << endl;
   }
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x %  y " << setw(12) << (x  & y) << " 0x" << setw(8) << setfill('0') << hex << (x  & y) <<  find(const_cast<type_info*>(&typeid(x  & y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x << y " << setw(12) << (x << y) << " 0x" << setw(8) << setfill('0') << hex << (x << y) <<  find(const_cast<type_info*>(&typeid(x << y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x >> y " << setw(12) << (x >> y) << " 0x" << setw(8) << setfill('0') << hex << (x >> y) <<  find(const_cast<type_info*>(&typeid(x >> y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  & y " << setw(12) << (x  & y) << " 0x" << setw(8) << setfill('0') << hex << (x  & y) <<  find(const_cast<type_info*>(&typeid(x  & y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  | y " << setw(12) << (x  | y) << " 0x" << setw(8) << setfill('0') << hex << (x  | y) <<  find(const_cast<type_info*>(&typeid(x  | y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  ^ x " << setw(12) << (x  ^ y) << " 0x" << setw(8) << setfill('0') << hex << (x  ^ y) <<  find(const_cast<type_info*>(&typeid(x  ^ y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << endl;
}
void func1(char x, unsigned long y) {
   ios_base::fmtflags ioFlags = cout.flags();
   cout << "func1(char " << (signed long)x << ", ulong " << y << ')' << endl;
   cout << "x  + y " << setw(12) << (x  + y) << " 0x" << setw(8) << setfill('0') << hex << (x  + y) <<  find(const_cast<type_info*>(&typeid(x + y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  - y " << setw(12) << (x  - y) << " 0x" << setw(8) << setfill('0') << hex << (x  - y) <<  find(const_cast<type_info*>(&typeid(x - y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  * y " << setw(12) << (x  * y) << " 0x" << setw(8) << setfill('0') << hex << (x  * y) <<  find(const_cast<type_info*>(&typeid(x * y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   if (y == 0) {
        cout << "x  / y " << x << " / 0" <<  endl;
   } else {
        cout << "x  / y " << setw(12) << (x  / y) << " 0x" << setw(8) << setfill('0') << hex << (x / y) <<  find(const_cast<type_info*>(&typeid(x / y))) << endl;
   }
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x %  y " << setw(12) << (x  & y) << " 0x" << setw(8) << setfill('0') << hex << (x  & y) <<  find(const_cast<type_info*>(&typeid(x  & y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x << y " << setw(12) << (x << y) << " 0x" << setw(8) << setfill('0') << hex << (x << y) <<  find(const_cast<type_info*>(&typeid(x << y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x >> y " << setw(12) << (x >> y) << " 0x" << setw(8) << setfill('0') << hex << (x >> y) <<  find(const_cast<type_info*>(&typeid(x >> y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  & y " << setw(12) << (x  & y) << " 0x" << setw(8) << setfill('0') << hex << (x  & y) <<  find(const_cast<type_info*>(&typeid(x  & y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  | y " << setw(12) << (x  | y) << " 0x" << setw(8) << setfill('0') << hex << (x  | y) <<  find(const_cast<type_info*>(&typeid(x  | y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  ^ x " << setw(12) << (x  ^ y) << " 0x" << setw(8) << setfill('0') << hex << (x  ^ y) <<  find(const_cast<type_info*>(&typeid(x  ^ y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << endl;
}
void func1(char x, long y) {
   ios_base::fmtflags ioFlags = cout.flags();
   cout << "func1(char " << (signed long)x << ", long " << y << ')' << endl;
   cout << "x  + y " << setw(12) << (x  + y) << " 0x" << setw(8) << setfill('0') << hex << (x  + y) <<  find(const_cast<type_info*>(&typeid(x + y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  - y " << setw(12) << (x  - y) << " 0x" << setw(8) << setfill('0') << hex << (x  - y) <<  find(const_cast<type_info*>(&typeid(x - y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  * y " << setw(12) << (x  * y) << " 0x" << setw(8) << setfill('0') << hex << (x  * y) <<  find(const_cast<type_info*>(&typeid(x * y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   if (y == 0) {
        cout << "x  / y " << x << " / 0" <<  endl;
   } else {
        cout << "x  / y " << setw(12) << (x  / y) << " 0x" << setw(8) << setfill('0') << hex << (x / y) <<  find(const_cast<type_info*>(&typeid(x / y))) << endl;
   }
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x %  y " << setw(12) << (x  & y) << " 0x" << setw(8) << setfill('0') << hex << (x  & y) <<  find(const_cast<type_info*>(&typeid(x  & y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x << y " << setw(12) << (x << y) << " 0x" << setw(8) << setfill('0') << hex << (x << y) <<  find(const_cast<type_info*>(&typeid(x << y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x >> y " << setw(12) << (x >> y) << " 0x" << setw(8) << setfill('0') << hex << (x >> y) <<  find(const_cast<type_info*>(&typeid(x >> y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  & y " << setw(12) << (x  & y) << " 0x" << setw(8) << setfill('0') << hex << (x  & y) <<  find(const_cast<type_info*>(&typeid(x  & y))) << endl;
cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  | y " << setw(12) << (x  | y) << " 0x" << setw(8) << setfill('0') << hex << (x  | y) <<  find(const_cast<type_info*>(&typeid(x  | y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << "x  ^ x " << setw(12) << (x  ^ y) << " 0x" << setw(8) << setfill('0') << hex << (x  ^ y) <<  find(const_cast<type_info*>(&typeid(x  ^ y))) << endl;
   cout.flags(ioFlags); cout << setfill(' ');
   cout << endl;
}

int main(int argc, char** argv) {
   char x = -1;
   func0((char) 1);

   func1(x, (char) 1);
   func1(x, (unsigned char) 1);
   func1(x, (long) 1);
   func1(x, (unsigned long) 1);
   sleep(1);
   return 0;
}
4

2 に答える 2

1

あなたの最初の結論は間違っています。C/C++ のすべての算術演算はint、少なくとも (または、おそらくunsigned int) サイズのドメイン内で計算を実行します。すべての小さいオペランド型 (など) はchar、実際の計算が開始される前に にshort昇格され、結果の型は になります。オペランドの型を保持するのは、前置バージョンと後置バージョンのような操作のみです。intint++--

これは、binary +、などの操作に適用されます。これは、およびにも適用されます。したがって、 andは他の算術演算子と何ら変わりはありません。*-<<>><<>>

どうやってそれを結論付けた"x op y is of type char if y is a char/unsigned char"のですか、私にはすぐにはわかりません. コードを実行したところ、期待される動作が確認されました。 および のような操作のみ++が型に--評価され、引数charに対する他のすべての操作は値に評価されます。charint

于 2012-12-17T22:32:46.743 に答える
0

先頭に以下を追加してコードをコンパイルした後、

typedef unsigned uint; //!
void sleep( int ) {} //!
#include <string> //!

正式な UB がまだいくつかありますが、それほど重要ではありません。

ただし、結果は次のことを示していません。

「y が char/unsigned char の場合、
x op y は char 型です。それ以外の場合、op が左/右シフトの場合を除き、x op y は y 型です」

どのコンパイラを使用していますか?

あなたが尋ねる、

「これは標準実装ですか?」

いいえ、標準的な実装はありません。ISO規格しかありません。

于 2012-12-17T22:32:30.507 に答える