为什么字符<<和字符>>中间结果 int
Why are char << and char >> intermediate results int
>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;
}
你最初的结论是不正确的。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
参数的所有其他操作的计算结果为int
值。
通过在顶部添加以下内容来编译代码后,
typedef unsigned uint; //!
void sleep( int ) {} //!
#include <string> //!
仍然有一些正式的UB,但应该无关紧要。
然而,结果并未表明
"x op y 是字符类型,如果 y 是字符/无符号字符
x op y 是 y 型,否则除非 op 是左/右移位"
您使用什么编译器?
你问,
"这是标准实现吗?"
嗯,不,没有标准的实现。只有一个ISO标准。
相关文章:
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- ///<评论></评论>在Visual Studio中