为什么一个运算符的操作数需要具有相同的类型
Why the operands of an operator needs to be of the same type?
如果我有这样的东西:
int i = 123;
float f = 123.1;
if (f > i) {} else {}
i
将被提升为float
,并且比较将变为if (float > float)
。我的问题是,为什么int
变量首先需要升级为float
,是因为计算机比较两个普通数字比试图弄清楚每个数字的位代表什么然后进行比较更容易吗?
因为"没有数字"。计算机不比较数字,也不处理数字。它们使用并比较位模式。
比特模式表示数字的事实是由于我们使用"编码"将数字表示为比特模式。一旦我们选择编码,对数字的运算就变成了对位模式的运算。一旦我们选择另一个编码,对数字的相同操作就变成了对比特模式的其他操作。
现在,如果你有10种可能的方法来表示数字,你应该支持100种可能的方式来进行二进制运算(如果你还想考虑结果的话,甚至可以支持1000种!(。
由于这无法扩展,您必须减少。减少的更简单方法是通过将相似的数字分解为多个部分来消除它们:首先将所有数字转换为通用编码,然后对该编码进行操作,最终将结果转换回所需的编码。
这主要是因为对具有相同编码的数字的运算可以很容易地实现,因为相同的规则适用于任何地方,并且这可以通过重用相同的电路来实现。
但要实现这一点,必须选择"通用格式",以便可以表示两个操作数。将int表示为float比将float表示为int有更多的成功机会。
规则是按原样编写的,因为编译器定义少量执行操作的方式以及规范化操作数的方式比定义大量方式更容易。即使只考虑int、unsigned int、long、unsignedlong、float、double这六种类型,在不转换操作数的情况下计算像x < y
这样的表达式也需要特殊情况代码来处理以下情况:
- int/unsigned int(按任意顺序(
- 长/无符号长
- int/float
- 长/浮动
- 长/双
在20世纪70年代,必须为x > y
处理16种不同的操作数类型组合,而不是6种,这将是非常昂贵的,特别是考虑到编译器必须生成更复杂的代码才能"准确"地执行这种比较,而不是将所有操作数强制为同一类型。
就我个人而言,我认为现代语言设计师应该从20世纪70年代的心态中解放出来,但它似乎已经得到了很好的证实(尽管也值得注意的是,如果"长双"的恶劣变量参数传递行为如果没有使该类型变得无用,该类型在许多平台上都能够表示每个long
或unsigned long
值的值,因此将固定的浮点/整数参数提升到该类型将很容易产生语义正确的结果(。
- 错误 C2679:二进制"<<":未找到采用类型 'std::string_view' 的右侧操作数的运算符(或者没有可接受的转换)
- 与'operator='不匹配(操作数类型'String'且"void")
- 不正确的操作数类型 MSVC
- C2678 二进制 '==':未找到采用 'Card' 类型左操作数的运算符(或者没有可接受的转换)
- 错误:类型"double()"和"double()"的操作数无效到二进制&quo
- C2679 二进制"<<":未找到采用右操作数类型的运算符
- int* 和 int[] 类型对二进制运算符 + 的操作数无效
- 错误:二进制'operator*' 'float'和'float[0]'类型的操作数无效
- 运算符'<'不能应用于类型 'string' 和 'string' 的操作数
- 非法,左操作数具有类型 'DWORD [29]'
- 错误 C2679 二进制"<<":未找到采用类型为 'T' 的右侧操作数的运算符
- 二进制 '==':未找到采用 'Enemy' 类型左侧操作数的运算符(或者没有可接受的转换)
- 错误:'operator>'不匹配(操作数类型为 'Student' 和 'Student'
- 与"运算符>>"不匹配(操作数类型为"QDataStream"和"QJsonObject")
- 类型"int"和"const char [15]"到二进制"运算符<<"的无效操作数^
- 与'operator<<'不匹配(操作数类型'std::ostream {aka std::basic_ostream<char>}'
- c++ 错误:二进制"运算符+"类型"矩阵*"和"矩阵*"的操作数无效
- c++运算符重载-我实际返回的操作数类型是什么
- 无效的类型操作数
- 如何计算重载运算符在具有特定类型操作数的代码库中使用的次数