C和C++运算符 (转)
这里是C和C++语言的运算符列表。所有列出的运算符皆含纳于C++;第三个栏目里的内容也使用C来描述。应当注意的是C不支持运算符重载。
下列运算符在两个语言中都是顺序点(运算符未重载时): &&、||、?: 和 ,(逗号运算符)。
C++也包含类型转换运算符const_cast、static_cast、dynamic_cast和reinterpret_cast,不在表中列出以维持简洁。类型转换运算符需要在表达式中明确使用括号,因此并不存在优先级的问题。
在C里有的运算符,除了逗号运算符和箭头记头的运算符以外,在Java、Perl、C#和PHP同样也有相同的优先级、结合性和语义。
运算符优先级
优先级 | 运算符 | 叙述 | 示例 | 重载性 | 结合性 |
---|---|---|---|---|---|
1 |
:: |
作用域解析(C++专有) | Class::age = 2; |
否 | 由左至右 |
2 |
++ |
后缀递增 | i++ | ||
-- |
后缀递减 | i-- | |||
{} |
组合 | {i++;a*=i;} | |||
() |
函数调用或变量初始化 | c_tor(int x, int y) : _x(x), _y(y * 10) {} | |||
[] |
数组访问 | array[4] = 2; | |||
. |
以对象方式访问成员 | obj.age = 34; | 否 | ||
-> |
以指针方式访问成员 | ptr->age = 34; | |||
dynamic_cast |
运行时检查类型转换(C++专有) | Y& y = dynamic_cast<Y&>(x); | 否 | ||
static_cast |
未经检查的类型转换(C++专有) | Y& y = static_cast<Y&>(x); | 否 | ||
reinterpret_cast |
重定义类型转换(C++专有) | int const* p = reinterpret_cast<int const*>(0x1234); | 否 | ||
const_cast |
更改非常量属性(C++专有) | int* q = const_cast<int*>(p); | 否 | ||
typeid |
获取类型信息(C++专有) | std::type_info const& t = typeid(x); | 否 | ||
3 |
++ |
前缀递增 | ++i | 由右至左 | |
-- |
前缀递减 | --i | |||
+ |
一元正号 | int i = +1; | |||
- |
一元负号 | int i = -1; | |||
! not |
逻辑非! 的备用拼写 |
if (!done) … | |||
~ compl |
按位取反~ 的备用拼写 |
flag1 = ~flag2; | |||
(type) |
强制类型转换 | int i = (int)floatNum; | |||
* |
取指针指向的值 | int data = *intPtr; | |||
& |
取变量的地址 | int *intPtr = &data; | |||
sizeof |
某某的大小 | size_t s = sizeof(int); | 否 | ||
new |
动态内存分配(C++专有) | long* pVar = new long; | |||
new[] |
动态数组内存分配(C++专有) | long* array = new long[20]; | |||
delete |
动态内存释放(C++专有) | delete pVar; | |||
delete[] |
动态数组内存释放(C++专有) | delete [] array; | |||
4 |
.* |
成员对象选择(C++专有) | obj.*var = 24; | 否 | 由左至右 |
->* |
成员指针选择(C++专有) | ptr->*var = 24; | |||
5 |
* |
乘法 | int i = 2 * 4; | ||
/ |
除法 | float f = 10.0 / 3.0; | |||
% |
模数(取余) | int rem = 4 % 3; | |||
6 |
+ |
加法 | int i = 2 + 3; | ||
- |
减法 | int i = 5 - 1; | |||
7 |
<< |
比特左移 | int flags = 33 << 1; | ||
>> |
比特右移 | int flags = 33 >> 1; | |||
8 |
< |
小于关系 | if (i < 42) … | ||
<= |
小于等于关系 | if (i <= 42) ... | |||
> |
大于关系 | if (i > 42) … | |||
>= |
大于等于关系 | if (i >= 42) ... | |||
9 |
== eq |
等于关系== 的备用拼写 |
if (i == 42) ... | ||
!= not_eq |
不等于关系!= 的备用拼写 |
if (i != 42) … | |||
10 |
& bitand |
比特 AND& 的备用拼写 |
flag1 = flag2 & 42; | ||
11 |
^ xor |
比特 XOR(独占or)^ 的备用拼写 |
flag1 = flag2 ^ 42; | ||
12 |
| bitor |
比特 OR(包含or)| 的备用拼写 |
flag1 = flag2 | 42; | ||
13 |
&& and |
逻辑 AND&& 的备用拼写 |
if (conditionA && conditionB) … | ||
14 |
|| or |
逻辑 OR|| 的备用拼写 |
if (conditionA || conditionB) ... | ||
15 |
c?t:f |
三元条件运算 | int i = a > b ? a : b; | 否 | 由右至左 |
16 |
= |
直接赋值 | int a = b; | ||
+= |
以和赋值 | a += 3; | |||
-= |
以差赋值 | b -= 4; | |||
*= |
以乘赋值 | a *= 5; | |||
/= |
以除赋值 | a /= 2; | |||
%= |
以取余数赋值 | a %= 3; | |||
<<= |
以比特左移赋值 | flags <<= 2; | |||
>>= |
以比特右移赋值 | flags >>= 2; | |||
&= and_eq |
以比特AND赋值&= 的备用拼写 |
flags &= new_flags; | |||
^= xor_eq |
以比特XOR赋值^= 的备用拼写 |
flags ^= new_flags; | |||
|= or_eq |
以比特OR赋值|= 的备用拼写 |
flags |= new_flags; | |||
17 |
throw |
抛出异常 | throw EClass(“Message”); | 否 | |
18 |
, |
逗号运算符 | for (i = 0, j = 0; i < 10; i++, j++) … | 由左至右 |
列表
在本表中,a
、b
和c
代表有效值(来自变量或返回值的逐字常数或数值)、对象名称,或适当的左值。
算术运算符[编辑] |
|||
运算符名称 | 语法 | 可重载 | C里有 |
---|---|---|---|
一元正号 | +a |
是 | 是 |
加法(总和) | a + b |
是 | 是 |
前缀递增 | ++a |
是 | 是 |
后缀递增 | a++ |
是 | 是 |
以加法赋值 | a += b |
是 | 是 |
一元负号(取反) | -a |
是 | 是 |
减法(差) | a - b |
是 | 是 |
前缀递减 | --a |
是 | 是 |
后缀递减 | a-- |
是 | 是 |
以减法赋值 | a -= b |
是 | 是 |
乘法(乘积) | a * b |
是 | 是 |
以乘法赋值 | a *= b |
是 | 是 |
除法(分之) | a / b |
是 | 是 |
以除法赋值 | a /= b |
是 | 是 |
模数(余数) | a % b |
是 | 是 |
以模数赋值 | a %= b |
是 | 是 |
比较运算符[编辑] |
|||
运算符名称 | 语法 | 可重载 | C里有 |
小于 | a < b |
是 | 是 |
小于或等于 | a <= b |
是 | 是 |
大于 | a > b |
是 | 是 |
大于或等于 | a >= b |
是 | 是 |
不等于 | a != b |
是 | 是 |
等于 | a == b |
是 | 是 |
逻辑取反 | !a |
是 | 是 |
逻辑 AND | a && b |
是 | 是 |
逻辑 OR | a || b |
是 | 是 |
比特运算符[编辑] |
|||
运算符名称 | 语法 | 可重载 | C里有 |
比特左移 | a << b |
是 | 是 |
以比特左移赋值 | a <<= b |
是 | 是 |
比特右移 | a >> b |
是 | 是 |
以比特右移赋值 | a >>= b |
是 | 是 |
比特一的补数 | ~a |
是 | 是 |
比特 AND | a & b |
是 | 是 |
以比特 AND 赋值 | a &= b |
是 | 是 |
比特 OR | a | b |
是 | 是 |
以比特 OR 赋值 | a |= b |
是 | 是 |
比特 XOR | a ^ b |
是 | 是 |
以比特 XOR 赋值 | a ^= b |
是 | 是 |
其它运算符[编辑] |
|||
运算符名称 | 语法 | 可重载 | C里有 |
基本赋值 | a = b |
是 | 是 |
函数调用 | a() |
是 | 是 |
数组下标 | a[b] |
是 | 是 |
间接(向下参考) | *a |
是 | 是 |
的地址(参考) | &a |
是 | 是 |
成员指针 | a->b |
是 | 是 |
成员 | a.b |
否 | 是 |
间接成员指针 | a->*b |
是 | 否 |
间接成员 | a.*b |
否 | 否 |
转换 | (type) a |
是 | 是 |
逗号 | a , b |
是 | 是 |
三元条件 | a ? b : c |
否 | 是 |
作用域解析 | a::b |
否 | 否 |
的大小 | sizeof a |
否 | 是 |
类型识别 | typeid type |
否 | 否 |
分配存储区 | new type |
是 | 否 |
解除分配存储区 | delete a |
是 | 否 |
语言扩展[编辑]
运算符名称 | 语法 | 可重载 | C里有 | 提供者 |
---|---|---|---|---|
标签值 | && label |
否 | 是 | GCC |
取得型态 | typeof a typeof(expr) |
否 | 是 | GCC |
最小/最大值 | a <? b a >? b |
否 | 否 | GCC |
注解[编辑]
在C和C++中对运算符的约束,是语言的语法规范因素所指定的(在对应的标准中),而不是优先级列表。这造成了一些微妙的冲突。例如,在C中,条件表达式的语法是:
邏輯-OR-表達式 ? 表達式 : 條件-表達式
在C++中则是:
邏輯-or-表達式 ? 表達式 : 賦值-表達式
因此,这个表达式:
e = a ? b : c = d
两个语言的语法分析结果并不相同。在C中,这个表达式被解析为:
e = ((a ? b : c) = d)
这是一个错误的语义,因为条件-表达式的结果并不是一个左值。在C++中,则解析为:
e = (a ? b : (c = d))
这是一个有效的表达式。
比特逻辑运算符的优先级一直受到批评[1]。在观念里,&和|是类似于+和*的数值运算符。但是,表达式
a & b == 7
意谓
a & (b == 7),
当
a + b == 7
意谓
(a + b) == 7。
这就需要经常使用圆括号,以免有意料之外的结果。
酉加运算符,可用于操作数表达式的类型提升。例如下例:
template <class T> void f(T const& a, T const& b){};
int main() {
int a[2];
int b[3];
f(a, b); // won't work! different values for "T"!
f(+a, +b); // works! T is "int*" both
}