Arithmetic operators
返回特定算术运算的结果。
| 运算符名称 | 语法 | 原型示例(针对 class T ) | ||
|---|---|---|---|---|
| 类内定义 | 类外定义 | |||
| 一元加号 | + a | T T :: operator + ( ) const ; | T operator + ( const T & a ) ; | |
| 一元减号 | - a | T T :: operator - ( ) const ; | T operator - ( const T & a ) ; | |
| 加法 | a + b | T T :: operator + ( const T2 & b ) const ; | T operator + ( const T & a, const T2 & b ) ; | |
| 减法 | a - b | T T :: operator - ( const T2 & b ) const ; | T operator - ( const T & a, const T2 & b ) ; | |
| 乘法 | a * b | T T :: operator * ( const T2 & b ) const ; | T operator * ( const T & a, const T2 & b ) ; | |
| 除法 | a / b | T T :: operator / ( const T2 & b ) const ; | T operator / ( const T & a, const T2 & b ) ; | |
| 取模 | a % b | T T :: operator % ( const T2 & b ) const ; | T operator % ( const T & a, const T2 & b ) ; | |
| 按位取反 | ~a | T T :: operator ~ ( ) const ; | T operator~ ( const T & a ) ; | |
| 按位与 | a & b | T T :: operator & ( const T2 & b ) const ; | T operator & ( const T & a, const T2 & b ) ; | |
| 按位或 | a | b | T T :: operator | ( const T2 & b ) const ; | T operator | ( const T & a, const T2 & b ) ; | |
| 按位异或 | a ^ b | T T :: operator ^ ( const T2 & b ) const ; | T operator ^ ( const T & a, const T2 & b ) ; | |
| 按位左移 | a << b | T T :: operator << ( const T2 & b ) const ; | T operator << ( const T & a, const T2 & b ) ; | |
| 按位右移 | a >> b | T T :: operator >> ( const T2 & b ) const ; | T operator >> ( const T & a, const T2 & b ) ; | |
|
||||
目录 |
通用说明
所有内置算术运算符均计算特定算术运算的结果并返回其值。参数不会被修改。
转换
如果传递给内置算术运算符的操作数是整型或无作用域枚举类型,那么在执行任何其他操作之前(但在适用的情况下进行左值到右值转换后),该操作数将进行 整型提升 。如果操作数具有数组或函数类型,则会应用 数组到指针 和 函数到指针 的转换。
对于二元运算符(移位运算符除外),如果提升后的操作数具有不同类型,则应用 常用算术转换 规则。
溢出
无符号整数运算始终以
2
n
为模执行,其中 n 是该特定整数的位数。例如对于
unsigned
int
,将
UINT_MAX
加一得到
0
,而从
0
减一得到
UINT_MAX
。
当有符号整数算术运算溢出(结果无法容纳于结果类型中)时,其行为是未定义的——此类运算可能的表现形式包括:
- 它根据表示规则(通常是 二进制补码 )进行回绕,
-
它产生陷阱——在某些平台或由于编译器选项(例如GCC和Clang中的
-ftrapv), - 它饱和至最小值或最大值(在许多DSP上),
- 它被编译器 完全优化消除 。
浮点环境
如果支持
#pragma STDC FENV_ACCESS
并设置为
ON
,则所有浮点算术运算符都将遵循当前浮点
舍入方向
,并按照
math_errhandling
中的规定报告浮点算术错误,除非属于
静态初始化器
的一部分(此时不会引发浮点异常且舍入模式为就近舍入)。
浮点收缩
除非支持并设置了
#pragma STDC FP_CONTRACT
为
OFF
,否则所有浮点运算都可能以中间结果具有无限范围和精度的方式执行,即允许省略舍入误差和浮点异常的优化。例如,C++ 允许使用单条融合乘加 CPU 指令实现
(
x
*
y
)
+
z
,或将
a
=
x
*
x
*
x
*
x
;
优化为
tmp
=
x
*
x
;
a
=
tmp
*
tmp
。
与契约无关,浮点运算的中间结果可能具有与其类型所示不同的范围和精度,详见 FLT_EVAL_METHOD 。
正式而言,C++标准对浮点运算的精确性不作任何保证。
一元算术运算符
一元算术运算符表达式的形式为
+
表达式
|
(1) | ||||||||
-
表达式
|
(2) | ||||||||
一元运算符
+
和
-
具有比所有二元算术运算符更高的
优先级
,因此
表达式
不能包含顶层的二元算术运算符。这些运算符采用从右向左的结合性:
+a - b; // 等价于 (+a) - b,而非 +(a - b) -c + d; // 等价于 (-c) + d,而非 -(c + d) +-e; // 等价于 +(-e),若“e”为内置类型则一元+是空操作 // 因为所有可能的提升已在取负操作期间完成
内置一元算术运算符
-a ,其中 N 表示提升后的位宽。
- 换言之,该运算结果是操作数的二进制补码(操作数与结果均视为无符号数)。
重载
在
针对用户定义运算符的重载决议
中,对于每个无cv限定符的提升算术类型
A
和每个类型
T
,以下函数签名会参与重载决议:
|
A operator
+
(
A
)
|
||
|
T
*
operator
+
(
T
*
)
|
||
|
A operator
-
(
A
)
|
||
标签内的C++代码均未翻译,仅对页面说明性文字进行了简体中文翻译。由于原始网页内容中除代码外无其他可翻译文本,故输出保持原样)
#include <iostream> int main() { char c = 0x6a; int n1 = 1; unsigned char n2 = 1; unsigned int n3 = 1; std::cout << "char: " << c << " int: " << +c << "\n" "-1, where 1 is signed: " << -n1 << "\n" "-1, where 1 is unsigned char: " << -n2 << "\n" "-1, where 1 is unsigned int: " << -n3 << '\n'; char a[3]; std::cout << "size of array: " << sizeof a << "\n" "size of pointer: " << sizeof +a << '\n'; }
可能的输出:
char: j int: 106 -1, where 1 is signed: -1 -1, where 1 is unsigned char: -1 -1, where 1 is unsigned int: 4294967295 size of array: 3 size of pointer: 8
加法运算符
加法运算符表达式具有以下形式
lhs
+
rhs
|
(1) | ||||||||
lhs
-
rhs
|
(2) | ||||||||
二元运算符
+
和
-
的
优先级
高于除
*
、
/
和
%
之外的所有其他二元算术运算符。这些运算符遵循从左到右的结合性:
a + b * c; // 等价于 a + (b * c),而非 (a + b) * c d / e - f; // 等价于 (d / e) - f,而非 d / (e - f) g + h >> i; // 等价于 (g + h) >> i,而非 g + (h >> i) j - k + l - m; // 等价于 ((j - k) + l) - m
内置加法运算符
对于内置二元加法和二元减法运算符, lhs 和 rhs 都必须是纯右值,且必须满足以下条件之一:
- 两个操作数都具有算术类型或无作用域枚举类型。此时,对两个操作数执行 常规算术转换 。
- 仅有一个操作数具有整数类型或无作用域枚举类型。此时,对该操作数应用整数提升。
在本节剩余描述中,"操作数"、 lhs 和 rhs 均指经过转换或提升后的操作数。
- 两个操作数均具有算术类型。此时结果为操作数之和。
- 一个操作数是指向完整定义对象类型的指针,另一个操作数具有整型类型。此时整型值会与指针相加(参见 指针算术 )。
如果两个操作数都具有浮点类型,且该类型支持 IEEE 浮点算术(参见 std::numeric_limits::is_iec559 ):
- 若任一操作数为 NaN,则结果为 NaN。
- 无穷大减无穷大为 NaN,并引发 FE_INVALID 。
- 正无穷大加负无穷大为 NaN,并引发 FE_INVALID 。
指针算术
当一个具有整数类型的表达式 J 与一个指针类型的表达式 P 相加或相减时,结果的类型与 P 的类型相同。
- 如果 P 求值为 空指针值 且 J 求值为 0 ,则结果为空指针值。
-
否则,如果
P
指向具有
n
个元素的数组对象
x
的第
i个元素,且给定 J 的值为 j ,则按以下方式对 P 进行加减运算:
-
- 表达式 P + J 和 J + P
-
-
当
i
+
j
在
[ 0 ,n)范围内时,指向 x 的第i+j个元素 - 当 i + j 等于 n 时,指向 x 最后一个元素之后的位置
-
当
i
+
j
在
- 表达式 P - J
-
-
当
i
-
j
在
[ 0 ,n)范围内时,指向 x 的第i-j个元素 - 当 i - j 等于 n 时,指向 x 最后一个元素之后的位置
-
当
i
-
j
在
- 其他 j 值将导致未定义行为
- 否则,若 P 指向一个完整对象、基类子对象或成员子对象 y ,且给定 J 的值为 j ,则 P 按如下规则进行加减运算:
-
- 表达式 P + J 和 J + P
-
- 当 j 为 0 时指向 y ,且
- 当 j 为 1 时指向 y 的末尾后位置。
- 表达式 P - J
-
- 当 j 为 0 时指向 y ,且
- 当 j 为 - 1 时指向 y 的末尾后位置。
- 其他 j 值将导致未定义行为。
- 否则,若 P 是指向对象 z 末尾之后位置的指针,且给定 J 的值为 j :
-
- 若 z 是具有 n 个元素的数组对象,则 P 的加减运算遵循以下规则:
-
- 表达式 P + J 与 J + P
-
-
当
n
+
j
处于区间
[ 0 ,n)时,指向 z 的第n+j个元素; - 当 j 为 0 时,指向 z 最后一个元素之后的位置。
-
当
n
+
j
处于区间
- 表达式 P - J
-
-
当
n
-
j
处于区间
[ 0 ,n)时,指向 z 的第n-j个元素; - 当 j 为 0 时,指向 z 最后一个元素之后的位置。
-
当
n
-
j
处于区间
- 其他 j 取值将导致未定义行为。
- 其他情况下, P 的加减运算遵循以下规则:
-
- 表达式 P + J 与 J + P
-
- 当 j 为 - 1 时,指向 z ;
- 当 j 为 0 时,指向 z 末尾之后的位置。
- 表达式 P - J
-
- 当 j 为 1 时,指向 z ;
- 当 j 为 0 时,指向 z 末尾之后的位置。
- 其他 j 取值将导致未定义行为。
- 否则,行为是未定义的。
当两个指针表达式 P 和 Q 相减时,结果的类型为 std::ptrdiff_t 。
- 如果 P 和 Q 均求值为 空指针值 ,则结果为 0 。
-
否则,如果
P
和
Q
分别指向同一数组对象
x
的第
i个和第j个数组元素,则表达式 P - Q 的值为 i − j 。
-
- 如果 i − j 无法由 std::ptrdiff_t 表示,则行为未定义。
- 否则,若 P 与 Q 指向同一完整对象、基类子对象或成员子对象,则结果为 0 。
- 否则,行为未定义。
这些指针算术运算符允许指针满足 LegacyRandomAccessIterator 要求。
对于加减运算,若
P
或
Q
具有“指向(可能带 cv 限定符的)
T
的指针”类型,且
T
与数组元素类型不
相似
,则行为未定义:
int arr[5] = {1, 2, 3, 4, 5}; unsigned int *p = reinterpret_cast<unsigned int*>(arr + 1); unsigned int k = *p; // 正确:变量“k”的值为2 unsigned int *q = p + 1; // 未定义行为:“p”指向的是int类型,而非unsigned int类型
重载
在
针对用户定义运算符的重载决议
中,对于每对提升后的算术类型
L
和
R
,以及每个对象类型
T
,以下函数签名会参与重载决议:
|
LR operator
+
(
L, R
)
|
||
|
LR operator
-
(
L, R
)
|
||
|
T
*
operator
+
(
T
*
,
std::
ptrdiff_t
)
|
||
|
T
*
operator
+
(
std::
ptrdiff_t
, T
*
)
|
||
|
T
*
operator
-
(
T
*
,
std::
ptrdiff_t
)
|
||
|
std::
ptrdiff_t
operator
-
(
T
*
, T
*
)
|
||
其中
LR
是对
L
和
R
进行
常规算术转换
的结果。
#include <iostream> int main() { char c = 2; unsigned int un = 2; int n = -10; std::cout << " 2 + (-10), where 2 is a char = " << c + n << "\n" " 2 + (-10), where 2 is unsigned = " << un + n << "\n" " -10 - 2.12 = " << n - 2.12 << '\n'; char a[4] = {'a', 'b', 'c', 'd'}; char* p = &a[1]; std::cout << "Pointer addition examples: " << *p << *(p + 2) << *(2 + p) << *(p - 1) << '\n'; char* p2 = &a[4]; std::cout << "Pointer difference: " << p2 - p << '\n'; }
输出:
2 + (-10), where 2 is a char = -8 2 + (-10), where 2 is unsigned = 4294967288 -10 - 2.12 = -12.12 Pointer addition examples: bdda Pointer difference: 3
乘法运算符
乘法运算符表达式具有以下形式
lhs
*
rhs
|
(1) | ||||||||
lhs
/
rhs
|
(2) | ||||||||
lhs
%
rhs
|
(3) | ||||||||
乘法运算符的 优先级 高于所有其他二元算术运算符。这些运算符从左向右结合:
a + b * c; // 等价于 a + (b * c),而非 (a + b) * c d / e - f; // 等价于 (d / e) - f,而非 d / (e - f) g % h >> i; // 等价于 (g % h) >> i,而非 g % (h >> i) j * k / l % m; // 等价于 ((j * k) / l) % m
内置乘法运算符
对于内置乘法和除法运算符,两个操作数必须具有算术类型或无作用域枚举类型。对于内置取余运算符,两个操作数必须具有整数类型或无作用域枚举类型。 常规算术转换 会在两个操作数上执行。
在本节剩余描述中,"操作数"、 lhs 和 rhs 均指转换后的操作数。
- NaN 与任意数字相乘均得到 NaN。
- 无穷大与零相乘得到 NaN 并引发 FE_INVALID 。
- 若任一操作数为 NaN,结果为 NaN。
- 非零数除以 ±0.0 将得到正确符号的无穷大,并触发 FE_DIVBYZERO 。
- 0.0 除以 0.0 将得到 NaN,并触发 FE_INVALID 。
注意:在 CWG issue 614 解决之前(通过 N2757 ),若二元运算符 % 的一个或两个操作数为负数,余数的符号由实现定义,因为这取决于整数除法的舍入方向。在此情况下,函数 std::div 提供了明确的行为定义。
注意:关于浮点数取余,请参阅 std::remainder 和 std::fmod 。
重载
在
针对用户定义运算符的重载决议
中,对于每对提升的算术类型
LA
和
RA
,以及每对提升的整型类型
LI
和
RI
,以下函数签名会参与重载决议:
|
LRA operator
*
(
LA, RA
)
|
||
|
LRA operator
/
(
LA, RA
)
|
||
|
LRI operator
%
(
LI, RI
)
|
||
其中
LRx
是对
Lx
和
Rx
进行
常规算术转换
的结果。
#include <iostream> int main() { char c = 2; unsigned int un = 2; int n = -10; std::cout << "2 * (-10), where 2 is a char = " << c * n << "\n" "2 * (-10), where 2 is unsigned = " << un * n << "\n" "-10 / 2.12 = " << n / 2.12 << "\n" "-10 / 21 = " << n / 21 << "\n" "-10 % 21 = " << n % 21 << '\n'; }
输出:
2 * (-10), where 2 is a char = -20 2 * (-10), where 2 is unsigned = 4294967276 -10 / 2.12 = -4.71698 -10 / 21 = 0 -10 % 21 = -10
位逻辑运算符
位逻辑运算符表达式的形式为
~
rhs
|
(1) | ||||||||
lhs
&
rhs
|
(2) | ||||||||
lhs
|
rhs
|
(3) | ||||||||
lhs
^
rhs
|
(4) | ||||||||
位非运算符的 优先级 高于所有二元算术运算符。其结合性为从右至左:
~a - b; // 等价于 (~a) - b,而非 ~(a - b) ~c * d; // 等价于 (~c) * d,而非 ~(c * d) ~-e; // 等价于 ~(-e)
当
~
后接
类型名称
或
decltype
说明符
(C++11 起)
时,语法存在歧义:它既可能表示运算符~,也可能是
析构函数
标识符的开头)。该歧义通过将
~
视为运算符~来解决。
~
仅在构成运算符~在语法上无效的位置才能作为析构函数标识符的开头。
所有其他位逻辑运算符的 优先级 均低于其他所有二元算术运算符。位与运算符的优先级高于位异或运算符,而位异或运算符的优先级又高于位或运算符。这些运算符均具有从左到右的结合性:
a & b * c; // 等价于 a & (b * c),而非 (a & b) * c d / e ^ f; // 等价于 (d / e) ^ f,而非 d / (e ^ f) g << h | i; // 等价于 (g << h) | i,而非 g << (h | i) j & k & l; // 等价于 (j & k) & l m | n ^ o // 等价于 m | (n ^ o)
内置位运算逻辑运算符
对于内置的按位取反运算符, rhs 必须是整数类型或无作用域枚举类型的纯右值,并对 rhs 执行整数提升。对于其他内置的按位逻辑运算符,两个操作数都必须具有整数类型或无作用域枚举类型,并对两个操作数执行 常规算术转换 。
在本节剩余描述中,"操作数"、 lhs 和 rhs 均指经过转换或提升后的操作数。
- 换言之,该结果是操作数的反码(操作数与结果均视为无符号数)。
重载
在
针对用户定义运算符的重载决议
中,对于每对提升后的整数类型
L
和
R
,以下函数签名会参与重载决议:
|
R operator~
(
R
)
|
||
|
LR operator
&
(
L, R
)
|
||
|
LR operator
^
(
L, R
)
|
||
|
LR operator
|
(
L, R
)
|
||
其中
LR
是对
L
和
R
进行
常规算术转换
的结果。
#include <bitset> #include <cstdint> #include <iomanip> #include <iostream> int main() { std::uint16_t mask = 0x00f0; std::uint32_t x0 = 0x12345678; std::uint32_t x1 = x0 | mask; std::uint32_t x2 = x0 & ~mask; std::uint32_t x3 = x0 & mask; std::uint32_t x4 = x0 ^ mask; std::uint32_t x5 = ~x0; using bin16 = std::bitset<16>; using bin32 = std::bitset<32>; std::cout << std::hex << std::showbase << "Mask: " << mask << std::setw(49) << bin16(mask) << "\n" "Value: " << x0 << std::setw(42) << bin32(x0) << "\n" "Setting bits: " << x1 << std::setw(35) << bin32(x1) << "\n" "Clearing bits: " << x2 << std::setw(34) << bin32(x2) << "\n" "Selecting bits: " << x3 << std::setw(39) << bin32(x3) << "\n" "XOR-ing bits: " << x4 << std::setw(35) << bin32(x4) << "\n" "Inverting bits: " << x5 << std::setw(33) << bin32(x5) << '\n'; }
输出:
Mask: 0xf0 0000000011110000 Value: 0x12345678 00010010001101000101011001111000 Setting bits: 0x123456f8 00010010001101000101011011111000 Clearing bits: 0x12345608 00010010001101000101011000001000 Selecting bits: 0x70 00000000000000000000000001110000 XOR-ing bits: 0x12345688 00010010001101000101011010001000 Inverting bits: 0xedcba987 11101101110010111010100110000111
位运算符
按位移位运算符表达式的形式为
lhs
<<
rhs
|
(1) | ||||||||
lhs
>>
rhs
|
(2) | ||||||||
位运算移位运算符的 优先级 高于位运算逻辑运算符,但低于加法和乘法运算符。这些运算符从左向右结合:
a >> b * c; // 等价于 a >> (b * c),而非 (a >> b) * c d << e & f; // 等价于 (d << e) & f,而非 d << (e & f) g << h >> i; // 等价于 (g << h) >> i,而非 g << (h >> i)
内建位运算移位运算符
对于内置的按位移位运算符,两个操作数必须是整型或无作用域枚举类型的纯右值。两个操作数都会执行整型提升。
在本节剩余描述中,“操作数”、“ a ”、“ b ”、“ lhs ”和“ rhs ”均指经过转换或提升后的操作数。
如果 rhs 的值为负数或不小于 lhs 的位数,则行为未定义。
|
对于无符号类型
a
,
a
<<
b
的值为
a * 2
b
对于有符号且非负的
a
,若
a * 2
b
对于负值 a , a << b 的行为未定义。
对于无符号类型
a
及有符号且非负的
a
,
a
>>
b
的值为
a/2
b
对于负值 a , a >> b 的值由实现定义(在大多数实现中执行算术右移,因此结果保持为负)。 |
(until C++20) |
|
a
<<
b
的值为与
a * 2
b
a
>>
b
的值为
a/2
b
|
(since C++20) |
结果的类型与 lhs 的类型相同。
重载
在
针对用户定义运算符的重载决议
中,对于每对提升后的整型类型
L
和
R
,以下函数签名会参与重载决议:
|
L operator
<<
(
L, R
)
|
||
|
L operator
>>
(
L, R
)
|
||
标签内的C++代码均未翻译,仅对页面结构进行了中文说明。实际内容中无需要翻译的自然语言文本)
#include <iostream> enum { ONE = 1, TWO = 2 }; int main() { std::cout << std::hex << std::showbase; char c = 0x10; unsigned long long ull = 0x123; std::cout << "0x123 << 1 = " << (ull << 1) << "\n" "0x123 << 63 = " << (ull << 63) << "\n" // 无符号数溢出 "0x10 << 10 = " << (c << 10) << '\n'; // char 被提升为 int long long ll = -1000; std::cout << std::dec << "-1000 >> 1 = " << (ll >> ONE) << '\n'; }
输出:
0x123 << 1 = 0x246 0x123 << 63 = 0x8000000000000000 0x10 << 10 = 0x4000 -1000 >> 1 = -500
标准库
算术运算符为许多标准库类型进行了重载。
一元算术运算符
|
实现一元加法和一元减法
(
std::chrono::duration<Rep,Period>
的公开成员函数)
|
|
|
对复数应用一元运算符
(函数模板) |
|
|
对valarray的每个元素应用一元算术运算符
(
std::valarray<T>
的公开成员函数)
|
加法运算符
|
(C++11)
|
对时间点执行加减运算
(函数模板) |
|
实现以时长为参数的算术运算
(函数模板) |
|
|
(C++20)
|
对
year_month_day
加减若干年或月
(函数) |
|
连接两个字符串、字符串与
char
,或字符串与
string_view
(函数模板) |
|
|
前进或回退迭代器
(
std::reverse_iterator<Iter>
的公开成员函数)
|
|
|
前进或回退迭代器
(
std::move_iterator<Iter>
的公开成员函数)
|
|
|
对两个复数或复数与标量执行复数算术运算
(函数模板) |
|
|
对两个 valarray 或 valarray 与值的每个元素应用二元运算符
(函数模板) |
乘法运算符
|
实现以时长为参数的算术运算
(函数模板) |
|
|
对两个复数或复数与标量执行复数算术运算
(函数模板) |
|
|
对两个 valarray 的每个元素或 valarray 与值应用二元运算符
(函数模板) |
位逻辑运算符
|
执行二进制与、或、异或及非运算
(
std::bitset<N>
的公开成员函数)
|
|
|
对位集执行二进制逻辑运算
(函数模板) |
|
|
对 valarray 的每个元素应用一元算术运算符
(
std::valarray<T>
的公开成员函数)
|
|
|
对两个 valarray 的每个元素或 valarray 与值之间应用二元运算符
(函数模板) |
位运算移位运算符
|
对两个 valarray 的每个元素或一个 valarray 与一个值应用二元运算符
(函数模板) |
|
|
执行二进制左移和右移操作
(
std::bitset<N>
的公开成员函数)
|
流插入/提取运算符
在整个标准库中,按位移位运算符通常被重载为以I/O流( std:: ios_base & 或其派生类之一)作为左操作数和返回类型。这类运算符被称为 流插入 和 流提取 运算符:
|
提取格式化数据
(
std::basic_istream<CharT,Traits>
的公开成员函数)
|
|
|
提取字符和字符数组
(函数模板) |
|
|
插入格式化数据
(
std::basic_ostream<CharT,Traits>
的公开成员函数)
|
|
|
插入字符数据或插入到右值流
(函数模板) |
|
|
序列化和反序列化复数
(函数模板) |
|
|
执行位集的流输入和输出
(函数模板) |
|
|
对字符串执行流输入和输出
(函数模板) |
|
|
(C++11)
|
对伪随机数引擎执行流输入和输出
(函数模板) |
|
(C++11)
|
对伪随机数分布执行流输入和输出
(函数模板) |
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 适用版本 | 发布时行为 | 正确行为 |
|---|---|---|---|
| CWG 614 | C++98 | 整数除法的代数商按实现定义的方向舍入 | 整数除法的代数商向零截断(小数部分被丢弃) |
| CWG 1450 | C++98 | 若 a / b 的结果无法用结果类型表示,则结果未指定 |
此情况下
a
/
b
和
a % b 的行为均未定义 |
| CWG 1457 | C++98 |
将有符号正数的最高有效
1
位移入符号位的行为未定义
|
改为明确定义 |
| CWG 1504 | C++98 | 指向数组元素基类子对象的指针可用于指针运算 | 此情况下行为未定义 |
| CWG 1515 | C++98 |
仅声明为
unsigned
的无符号整数
应遵守模 2 n 算术规则 |
适用于所有无符号整数 |
| CWG 1642 | C++98 | 算术运算符允许其操作数为左值 | 部分操作数必须为右值 |
| CWG 1865 | C++98 |
CWG 1504
的解决方案使得
当指向类型与数组元素类型在非顶层 具有不同 cv 限定时的指针算术行为未定义 |
改为明确定义 |
| CWG 1971 | C++98 |
解决
~
歧义的规则是否适用于
~X ( 0 ) 等情况不明确 |
该规则适用于此类情况 |
| CWG 2419 | C++98 |
仅当通过
&
获取指针时,
指向非数组对象的指针才会在指针算术中 被视为大小为1的数组的首元素指针 |
适用于所有指向非数组对象的指针 |
| CWG 2626 | C++98 |
内置
operator~
的结果仅简单描述为
'按位取反'而缺乏准确定义 |
改用二进制表示形式描述结果 |
| CWG 2724 | C++20 | 算术右移的舍入方向不明确 | 予以明确 |
| CWG 2853 | C++98 | 对象末尾之后的指针不能与整数进行加减运算 | 允许进行此类运算 |
参见
| 常用运算符 | ||||||
|---|---|---|---|---|---|---|
| 赋值 |
自增
自减 |
算术 | 逻辑 | 比较 |
成员
访问 |
其他 |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
...
]
|
函数调用
a ( ... ) |
|
逗号
a, b |
||||||
|
条件
a ? b : c |
||||||
| 特殊运算符 | ||||||
|
static_cast
将一种类型转换为另一种相关类型
|
||||||
|
C 文档
关于
算术运算符
|