cygwin gcc 4.5.3
我正在尝试确定C ++中各种计算中使用的中间结果。对于'char',我得到了以下结果(x是一个字符):
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;
}
答案 0 :(得分:1)
您的初步结论不正确。 C / C ++中的所有算术运算至少(或者,int
)在大小unsigned int
的域内执行计算。在任何实际计算开始之前,所有较小的操作数类型(char
,short
等)都会提升为int
,结果的类型为int
。只有++
和--
的前缀和后缀版本等操作才会保留其操作数的类型。
这适用于二元+
,*
,-
等操作。这同样适用于<<
和>>
。因此<<
和>>
与其他算术运算符没有任何区别。
你是如何得出结论的那样"x op y is of type char if y is a char/unsigned char"
对我来说并不是很清楚。我刚刚运行了您的代码并确认了预期的行为:只有++
和--
之类的操作评估为char
类型,而char
参数上的所有其他操作都评估为{{ 1}}值。
答案 1 :(得分:0)
通过在顶部添加以下代码来编译代码,
typedef unsigned uint; //!
void sleep( int ) {} //!
#include <string> //!
仍有一些正式的UB,但不应该真的重要。
结果不,但表示
“如果y是char / unsigned char,则x op y的类型为char x op y的类型为y,否则除了op左/右移“
您使用的是哪种编译器?
你问,
“这是标准实施吗?”
嗯,不,没有标准的实施。只有ISO标准。