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 |