3.1 赋值运算
FreeBASIC的赋值运算除了“=”以外,还有类似C语言的运算后赋值的操作,具体运算符及其说明如表3-1所示。
表3-1 赋值运算符及说明
运算符 |
说明 |
= |
为变量赋值一个值 |
&= |
追加并赋值一个字符串到另一个字符串,s1 &= s2等同于s1 = s1 & s2 |
+= |
添加并赋值给一个变量s1 += s2等同于s1 = s1 + s2 |
-= |
减去并赋值给一个变量s1 -= s2等同于s1 = s1 - s2 |
*= |
乘上一个变量并赋值给该变量s1 *= s2等同于s1 = s1 * s2 |
/= |
除以一个变量并赋值给该变量 s1 /= s2等同于s1 = s1 / s2 |
\= |
将一个变量整除并赋值给该变量 s1 \= s2等同于s1 = s1 \ s2 |
^= |
求一个变量指数并赋值给该变量s1 ^= s2等同于s1 = s1 ^ s2 |
Mod= |
将一个变量求余并赋值给该变量s1 Mod= s2等同于s1 = s1 Mod s2 |
And= |
与上一个变量并赋值给该变量s1 And= s2等同于s1 = s1 And s2 |
Or= |
或上一个变量并赋值给该变量s1 Or= s2等同于s1 = s1 Or s2 |
Xor= |
异或上一个变量并赋值给该变量s1 Xor= s2等同于s1 = s1 Xor s2 |
Eqv= |
同或上一个变量并赋值给该变量s1 Eqv= s2等同于s1 = s1 Eqv s2 |
Imp= |
蕴涵上一个变量并赋值给该变量s1 Imp= s2等同于s1 = s1 Imp s2 |
Shl= |
左移一个变量并赋值给该变量s1 Shl= s2等同于s1 = s1 Shl s2 |
Shr= |
右移一个变量并赋值给该变量s1 Shr= s2等同于s1 = s1 Shr s2 |
Let |
Let用于重载操作符 =(赋值)运算符,并将其与比较运算符操作符 = (Equal)区分开来。 |
Let() |
将用户定义类型的字段赋值给变量列表 |
3.2 算术运算
算术运算就是加、减、乘、除等运算,这里需要注意除法有“/”(除)和“\”(整除)的区别,具体运算符和说明如表3-2所示。
表3-2 算术运算符及说明
运算符 |
名称 |
说明 |
+ |
加 |
两个表达式相加 |
- |
减 |
两个表达式相减 |
* |
乘 |
两个表达式相乘 |
/ |
除 |
两个表达式相除(除法,可以有小数) |
\ |
整除 |
两个表达式整除(除法,没有小数) |
^ |
求幂 |
求表达式的指数 |
Mod |
求余 |
两个表达式求余 |
- |
取负 |
更改表达式符号(如5加上“-”后变成-5) |
3.3 条件运算
条件运算符是对表达式进行比较的运算,结果为真(True)或假(False),条件运算符及其说明如表3-3所示。
表3-3 条件运算符及说明
运算符 |
名称 |
说明 |
= |
等于 |
比较两个表达式是否相等 |
<> |
不等于 |
比较两个表达式是否不相等 |
< |
小于 |
比较表达式是否比另一个表达式小 |
<= |
小于等于 |
比较表达式是否比另一个表达式小或相等 |
> |
大于 |
比较表达式是否比另一个表达式大 |
>= |
大于等于 |
比较表达式是否比另一个表达式大或相等 |
Is |
检查对象是否与从其编译时类型派生的类型兼容 |
3.4 逻辑运算
逻辑运算有与、或、非、异或等运算,具体运算符及说明如表3-4所示。
表3-4 逻辑运算符及说明
运算符 |
名称 |
说明 | |||||||||||||||
And |
与 |
返回两个数值按位与的结果,真值表如下:(有0出0,全1出1)
| |||||||||||||||
Or |
或 |
返回两个数值按位或的结果,真值表如下:(有1出1,全0出0)
| |||||||||||||||
Not |
非 |
返回表达式按位非的结果,真值表如下:
| |||||||||||||||
Xor |
异或 |
返回两个数值异或的结果,真值表如下:(同出0,异出1)
| |||||||||||||||
Eqv |
等价 |
返回两个数值同或的结果,真值表如下:(同出1,异出0)
| |||||||||||||||
Imp |
蕴涵 |
返回两个数值蕴涵运算的结果,真值表如下:
| |||||||||||||||
AndAlso |
且 |
返回两个数值逻辑与的结果,真值表如下:
| |||||||||||||||
OrElse |
或 |
返回两个数值逻辑或的结果,真值表如下:
|
3.5 位运算
3.5.1 位运算说明
FreeBASIC中的与、或、非等也可以用于位运算操作,同时增加了位移操作,大大增强了位运算的功能。(虽然Xor,Eqv等也属于位操作,由于使用较少,此处不具体介绍),有关位操作的运算符和说明如表3-5所示。
表3-5 位运算符及说明
运算符 |
名称 |
说明 | |||||||||||||||
And |
与 |
返回两个数值按位与的结果,真值表如下:(有0出0,全1出1)
| |||||||||||||||
Or |
或 |
返回两个数值按位或的结果,真值表如下:(有1出1,全0出0)
| |||||||||||||||
Not |
非 |
返回表达式按位非的结果,真值表如下:
| |||||||||||||||
Shl |
左移 |
将数字表达式的位向左移动 | |||||||||||||||
Shr |
右移 |
将数字表达式的位向右移动 |
3.5.2 与逻辑运算比较
1、按位与操作与逻辑与操作
and为按位与操作,编译器会对数据的每一位都进行与操作,结果为两数与后的具体数值。如下所示:
'&B = 二进制,&O = 八进制,&H = 十六进制
'1、按位与 即C语言的&操作 '初始化a = 0x33 ' 00110011
Dim a As UByte = &B00110011 '与操作a & 0x01 ' & 00000001
Print a And &B00000001 '结果为 = 0x01 ' = 00000001
Print Hex(a And &B00110011) '结果为 = 0x33 ' = 00110011
'Hex是为了让数据以十六进制数的方式显示,方便观察比较
Sleep
andalso为逻辑与操作,即操作数不为0即为true,为0即为fasle。所得结果为false(0)或者true(-1,FB中的TRUE值为-1,C语言中的TRUE值为1,这里有区别),如下所示:
'&B = 二进制,&O = 八进制,&H = 十六进制
'2、逻辑与 即C语言的&&操作
Dim a As UByte = &B00110011 'b = 0x33(不为0,即为true)
Print a AndAlso &B00000001 '与 0x01(也不为0,也是true)
'结果为true(-1) true && true = true
Print a AndAlso &H00110011 '结果为true(-1)
sleep
2、按位或和逻辑或
or为按位或操作,编译器会对数据的每一位都进行或操作,结果为两数或后的具体数值。如下所示:
'&B = 二进制,&O = 八进制,&H = 十六进制
'1、按位或 (有1出1,全0出0)
Dim a As UByte = &B00110011 '初始化a = 0x33 ' 00110011
Print Hex(a or &B00000001) '或0x01 结果为0x33 ' | 00000001 = 00110011
Print Hex(a or &B11001100) '或0xcc 结果为0xff ' | 11001100 = 11111111
Sleep
orelse为逻辑或操作,两数逻辑或后所得结果为false(0)或者true(-1),如下所示:
'&B = 二进制,&O = 八进制,&H = 十六进制
'2、逻辑或
Dim a As UByte = &B00110011 'b = 0x33(不为0,即为true,为0则是False)
Print a OrElse &B00000001 '0x33与0x01 结果为true(-1)
Print a OrElse &B11001100 '0x33与0xcc 结果为true(-1)
Dim b As Boolean = FALSE '设置操作数是False
Print b OrElse FALSE 'False与False 结果为False(0)
Sleep
3、非操作
not是按位非操作,对于数值型数据,即对数据的每一位都进行取反操作,而对布尔型数据,则进行逻辑取反(即not true = false,not false = ture)如下所示:
'1、按位非 - 数值型数据
Dim a As UByte = &B00000011 'a = 0x03 not 0000 0011
Print Not a 'a = -4 not操作后会当成有符号数处理(实际-4就是0xfc)
Dim b As UByte = Not a '用无符号存储
Print b 'a = 0xfc = 1111 1100
Print CUByte(Not a) '如果需要转换后为无符号,则可以加一个强制转换
'2、按位非 - 布尔型数据
Dim c As Boolean = TRUE '定义布尔类型
Print c '打印数据 显示true
Print Not c '非操作后的数据 显示false
Sleep
FB只有一个not操作,没有逻辑非,所以如果需要按逻辑非操作时,必须谨慎对待,尽量使用布尔类型或者强制转换为布尔类型判断。如下所示:
'3、逻辑非
Dim c As Long = &B00000001
If Not c Then 'c是00000001,按位非后为11111110,数值上不为0
Print "c是0" '所以会执行这里的语句,与我们希望的逻辑非判断有出入
Else
Print "c非0"
EndIf
If Not cast(Boolean,c) Then '正确的方式是先强制转换c为布尔型,则非后也是布尔型
Print "c是0" 'c = true,not c = false
Else
Print "c非0" '所以会执行这里,与我们想要的逻辑判断吻合
EndIf
4、位移操作
位移操作有Shl(左移)和Shr(右移),即变量的值向左或向右移动指定位数。
语法:
'左移
Result = Variable shl MoveBits
'右移
Result = Variable shr MoveBits
'Shl和Shr前的Variable为位移的变量,后面的MoveBits为位移几位。
左移shl其实就是乘2操作,右移shr其实就是除2操作。这里需要注意,位移操作移动出数据类型大小的位就会直接抛弃,以下是两种数据类型的对比,右移与左移类似。
Dim a As UByte = &B00000011 'a = 0x03 '0000 0011
Dim b As UByte = a Shl 1 '左移1位,a=0x06 '0000 0110 '3 × 2 = 6
Print Bin(b)
b = a Shl 7 '左移7位,a=0x80 '1000 0000 '3 × 2 × 2 × 2 × 2 × 2 × 2 × 2 = 384
Print Bin(b) '但384已经超过256了,所以高位被截取,变成128
Dim c As ULong = a Shl 7 '同样左移7位,由于存储的数据类型不同
Print Bin(c) '位数足够,所以a = 0x180 '0001 1000 0000
'使用Bin函数,方便查看二进制值
Sleep
5、循环位移
循环位移即移出数据位的数据又从最低位继续进入该数据的操作,但FB并没有循环位移指令。所以我们自定义循环左移rol,参数x为需要移动的数,n为移动位数。测试例子如下:
#define rol(x,n) (((x) Shr (SizeOf(x) * 8 - (n))) Or ((x) Shl (n)))
#define ror(x,n) (((x) Shl (SizeOf(x) * 8 - (n))) Or ((x) Shr (n)))
Dim a As UByte = &Hc0 '1100 0000
Dim b As UByte = rol(a,1) '1000 0001
Print Bin(b)
a = &H03 '0000 0011
b = ror(a,2) '1100 0000
Print Bin(b)
Sleep
3.6 优先级
FreeBASIC的优先级如表3-6所示,从上到下优先级依次由高到低,同一区块的优先级相同。在程序设计时需要注意表达式的优先级,否则会出现不是自己需要的结果。对于运算符优先级不明确的表达式,建议将表达式的部分包含在括号中,以便尽可能减少错误,并有利于读者阅读代码。
表3-6 FreeBASIC优先级
操作者 |
描述 |
关联性 |
Cast |
类型转换 |
N/A |
ProcPtr |
程序指针 |
N/A |
StrPtr |
字符串指针 |
N/A |
VarPtr |
变量指针 |
N/A |
[] |
字符串索引 |
Left-to-Right |
[] |
指针索引 |
Left-to-Right |
() |
数组索引 |
Left-to-Right |
() |
函数调用 |
Left-to-Right |
. |
成员访问 |
Left-to-Right |
-> |
指向成员访问 |
Left-to-Right |
@ |
取地址 |
Right-to-Left |
* |
取数据值 |
Right-to-Left |
New |
赋值内存 |
Right-to-Left |
Delete |
取消赋值内存 |
Right-to-Left |
^ |
求幂 |
Left-to-Right |
- |
求反 |
Right-to-Left |
* |
乘 |
Left-to-Right |
/ |
除 |
Left-to-Right |
\ |
整除 |
Left-to-Right |
MOD |
求余 |
Left-to-Right |
SHL |
左移 |
Left-to-Right |
SHR |
右移 |
Left-to-Right |
+ |
加 |
Left-to-Right |
- |
减 |
Left-to-Right |
& |
字符串连接 |
Left-to-Right |
Is |
运行时类型信息检查 |
N/A |
= |
等于 |
Left-to-Right |
<> |
不等于 |
Left-to-Right |
< |
小于 |
Left-to-Right |
<= |
小于或等于 |
Left-to-Right |
> |
大于 |
Left-to-Right |
>= |
大于或等于 |
Left-to-Right |
NOT |
求位反码 |
Right-to-Left |
AND |
位逻辑与 |
Left-to-Right |
OR |
位逻辑或 |
Left-to-Right |
EQV |
等价 |
Left-to-Right |
IMP |
蕴涵 |
Left-to-Right |
XOR |
位异或 |
Left-to-Right |
ANDALSO |
逻辑与 |
Left-to-Right |
ORELSE |
逻辑或 |
Left-to-Right |
= |
赋值 |
N/A |
&= |
连接和赋值 |
N/A |
+= |
加法和赋值 |
N/A |
-= |
减法和赋值 |
N/A |
*= |
乘法和赋值 |
N/A |
/= |
除法和赋值 |
N/A |
\= |
整除和赋值 |
N/A |
^= |
指数和赋值 |
N/A |
MOD= |
求余和赋值 |
N/A |
AND= |
与和赋值 |
N/A |
EQV= |
等价和赋值 |
N/A |
IMP= |
蕴涵和赋值 |
N/A |
OR= |
或和赋值 |
N/A |
XOR= |
异或和赋值 |
N/A |
SHL= |
左移并赋值 |
N/A |
SHR= |
右移并赋值 |
N/A |
LET |
赋值 |
N/A |
LET() |
赋值 |
N/A |