运算符
如果存在变量,就可使用这些变量进行操作。为了能达到这样的目的,UnigineScript将运算符进行了集成。大多数的运算符 都是符合,但这些符号并不是字母表上的部分符号而是可在键盘上使用的变量符号。
数字运算符#
操作类型 | 运算符 | 类型 | 描述 | 运算对象类型 |
---|---|---|---|---|
取反 | - | 一元运算符 | 返回一个与运算对象相反的值(changes its sign to the opposite) | 标量, 矢量 |
增量 | ++ | 一元运算符 | 将运算对象的值加1 (支持前缀表示法及后缀表示法) | 标量 |
减量 | -- | 一元运算符 | 将运算对象的值减1 (支持前缀表示法及后缀表示法) | 标量 |
乘法 | * | 二元运算符 | 两个运算对象相乘 | 标量, 矢量 |
除法 | / | 二元运算符 | 用第二个运算对象除以第一个运算对象 | 标量,矢量 |
模运算 | % | 二元运算符 | 将第二个运算对象除以第一个运算对象的余数返回 | 整型,长整型, 浮点型 及双精度型 |
加法 | + | 二元运算符 | 将两个运算对象相加 | 标量, 矢量, 字符串 |
减法 | - | 二元运算符 | 将两个运算对象相减 | 标量, 矢量 |
int a = 0, b = 0;
log.message("%d %d\n",++a,b++);
log.message("%d %d\n",++a,b++);
log.message("%d %d\n",a,b);
/* Output:
* 1 0
* 2 1
* 2 2
*/
标量运算对象#
所有采用两种不同运算对象类型的数字运算符会执行标量的自动转换。转换的结构通常为两种类型中范围最大的类型。
矢量运算对象#
一些数字运算符会被运用到矢量类型。所有矢量类型可与相同类型的另一个运算对象进行添加,减法操作,乘法操作。而在不同类型的矢量运算对象或矢量甚至标量上进行运算时,仅可使用指定的结合运算符,因为大多数情况下矢量类型不可转换。
字符串运算符#
这些运算符仅将 字符串 变量作为运算对象。
运算类型 | 运算符 | 类型 | 描述 |
---|---|---|---|
字符串连接 | + | 二元运算符 | 两个运算对象被连接成一个字符串 |
字符串不仅可与字符串连接在一起,并且由于强制转换类型其还能与任意基本类型的变量连接在一起。
float a = -3.9;
string str = "there can be a mixture";
str = str + " of integer (" + 56 + ") and floating point values (" + a + ")";
log.message("%s\n", str);
/* 输出:
* there can be a mixture of integer (56) and floating point values (-3.9)
*/
逻辑运算符及位运算符#
这些运算符仅将下列类型的变量作为运算对象:
运算 | 运算符 | 类型 | 描述 | 运算对象类型 |
---|---|---|---|---|
逻辑非 | ! | 二元运算符 | 将布尔表达式取反 | 整型, 长整型 |
逻辑与 | && | 二元运算符 | 如果两个运算对象为真,则为真 | 整型, 长整型 |
逻辑或 | || | 二元运算符 | 如果一个或两个运算对象为真,则为真 | 整型, 长整型 |
按位取否 (补数) | ~ | 二元运算符 | 对每个位逻辑取反 | 整型, 长整型 |
按位与 | & | 二元运算符 | 对相应的每一对位进行逻辑与运算 | 整型, 长整型 |
按位或 | | | 二元运算符 | 对相应的每一对位进行逻辑或运算 | 整型, 长整型 |
按位异或 | ^ | 二元运算符 | 对相应的每一对位进行逻辑异或运算 | 整型, 长整型 |
左移 | << | 二元运算符 | 使用由第二个运算对象指定的位数量将第一个运算对象中的位模式移至左侧 | 整型,
长整型 ivec3 或 ivec4 也可为第一个运算对象 |
右移 | >> | 二元运算符 | 使用由第二个运算对象指定的位数量将第一个运算对象中的位模式移至右侧 | 整型, 长整型 ivec3 或 ivec4 也可为第一个运算对象 |
所有非0的值等同于真, 但如果需要为某些运算的结果返回为真,通常使用 1。 假 通常使用 0。
比较运算符#
- 由于标量的自动转换,不同类型的标量 (整型, 长整型, 浮点型, 双精度型)之间可自由进行比较。
- 矢量 (vec3, vec4, dvec3, dvec4, ivec3,ivec4, mat4, quat)仅可与 相同类型进行比较。
运算类型 | 运算符 | 描述 | 运算对象类型 |
---|---|---|---|
相等 | == | 检测两个运算对象是否相等 | 标量,矢量,字符串 整型(0) 可被比作空字符串 和v.v. |
不相等 | != | 检测两个运算对象是否不相等 | 标量,矢量,字符串 整型(0) 可被比作空 字符串 和 v.v. |
小于 | < | 检测第一个运算对象是否比第二个运算对象小 | 标量,字符串 |
大于 | > | 检测第一个运算对象是否比第二个运算对象大 | 标量,字符串 |
小于等于 | <= | 检测第一个运算对象是否小于等于第二个运算对象 | 标量,字符串 |
大于等于 | >= | 检测第一个运算对象是否大于等于第二个运算对象 | 标量,字符串 |
如果语句为真,运算符返回1,否则就返回0。
赋值运算符#
运算类型 | 运算符 | 类型 | 描述 |
---|---|---|---|
赋值 | = | 二元运算符 | 将第二个运算对象的值赋给第一个运算对象 |
"If-then-else" 替换 | ? : | 三元运算符 | 如果整个表达式为第二个赋值的运算对象,可用于条件赋值 |
条件运算符?: 可作为"if-then-else"结构中单行模块内容的简写进行使用。如果使用得当,此运算符可增加代码的可读性。其语法如下:test_expression1 ? then_expression : else_expression。
int a = 10;
int b;
b = (a > 9) ? 100 : 200; // 三元运算符的用法
// 此表达式等同于上一个表达式
if(a > 9) {
b = 100;
} else {
b = 200;
}
log.message("b =" + (b))
/* 输出:
* b = 200
*/
也可在表达式内使用 ?:运算符。例如:
int a = 1;
int b = 2;
int c = 3;
int d = 4;
log.message("%s\n","test 1: " + (a == b) ? "a == b" : "a != b" + " final");
log.message("%s\n","test 2: " + ((c == d) ? "c == d" : "c != d") + " final");
log.message("%s\n","test 3: " + (a == b) ? "a == b and " + ((c == d) ? "c == d" : "c != d") : ("a != b and " + ((c == d) ? "c == d" : "c != d")));
test1: a != b final
test2: c != d final
test3: a != b and c != d
赋值运算符 = 可与 +, -, *, /, %, &, | 和^结合使用。 这些合并运算符(+=, -=, *=, /=, %=, &=, |=和 ^=) 会将运算结果赋值给第一个运算对象(此对象必须为变量)。
int a = 10;
int b, c;
a = b = c; // 此语句不会得以执行
a = b += c; // 此语句也不会得以执行
访问运算符#
运算类型 | 运算符 | 类型 | 描述 |
---|---|---|---|
访问成员 | . | 二元运算符 | 访问第一个运算对象的成员(第二个运算对象)。可随同下列对象一起使用: |
范围解析 | :: |
|
在标识符范围外对其进行访问。欲了解细节,请参看范围解析运算符。 |
使用索引进行访问 | [] | 二元运算符 | 通过元素索引对其进行访问。可随同类,矢量,贴图,vec3, vec4, mat4和quat一起使用 |
类型测试运算符#
类型测试运算符用来检测所给变量的类型。 在下列情况下,运算符会返回1 :
- 所给变量属于某种规定的类型
- 所给对象是某个指定类的实例
- 所给对象是某个类的实例,这个类由某个指定类派生而来
此运算符的语法如下:
i is int
- 标量类型的一种
- 矢量类型的一种
- 字符串
- 用户定义的类的名称
- 外部类的名称
例如此运算符可在if-else语句中使用:
class Foo { };
class Bar : Foo { };
void check(int v) {
string s = typeinfo(v);
// is 运算符和is_int()函数都会检查v是否为整型
if(v is int) log.message("%s is int\n",s);
if(is_int(v)) log.message("%s is int\n",s);
// 检查v是否为浮点类型
if(v is float) log.message("%s is float\n",s);
if(is_float(v)) log.message("%s is float\n",s);
// 检查v是否为Stream类或由Stream派生类的实例
if(v is Stream) log.message("%s is Stream\n",s);
// 检查v是否为File类的实例
if(v is File) log.message("%s is File\n",s);
// 检查v是否为Foo或Bar类的实例
if(v is Foo) log.message("%s is Foo\n",s);
// 检查v是否为Bar类的实例
if(v is Bar) log.message("%s is Bar\n",s);
}
check(1);
check(1.0f);
check(new File());
check(new Foo());
check(new Bar());
int: 1 is int
int: 1 is int
float: 1 is int
float: 1 is int
File 000000000E9330E0 internal (5:0:0) is Stream
File 000000000E9330E0 internal (5:0:0) is File
Foo 000000000D06FCD0 (131072:0:0) is Foo
Bar 000000000D06FD00 (196608:0:0) is Foo
Bar 000000000D06FD00 (196608:0:0) is Bar
运算符的优先顺序#
如果表达式内有数个运算符,程序会按照如下表所列的优先顺序进行处理,优先级按照从上至下的顺序由高到低。
运算类型 | 运算符 |
---|---|
括号 | () |
访问运算符 | [] . |
一元运算符 | ! - + ++ -- |
乘法运算符 | * / |
加法运算符,字符串连接 | + - |
移位运算符 | << >> |
比较运算符 | == != < > <= >= |
按位取否 | ~ |
按位与 | & |
按位异或 | ^ |
按位或 | | |
逻辑非 | ! |
逻辑与 | && |
逻辑或 | || |
赋值运算符 | = += -= *= /= %= &= |= ^= ?: |
运算符重载#
可在此处了解运算符重载