delphi基础01-表达式、运算符、函数调用、集合构造函数、索引、(值或变量)类型转换
整理出来,供大家学习使用:
http://docwiki.embarcadero.com/RADStudio/Rio/en/Expressions_(Delphi)#Typecasts
1、表达式:
表达式是一种返回值的构造。下表为Delphi表达式示例:
|
变量 |
|
变量X的地址 |
|
整数常数 |
|
变量 |
|
函数调用 |
|
X和Y的乘积 |
|
Z和(1-Z)的商 |
|
布尔型 |
|
布尔型 |
|
布尔取反 |
|
组 |
|
值类型转换 |
最简单的表达式是变量和常量(在关于数据类型(Delphi)中描述)。使用运算符,函数调用,集合构造函数,索引和类型转换,从较简单的表达式构建更复杂的表达式。
2、运算符
2.1、算术运算符
采用实数或整数操作数的算术运算符包括+,-,*,/,div和mod。
10进制算术运算符:
操作(运算符) | 运作方式 | 操作数类型 | 结果类型 | 例 |
---|---|---|---|---|
+ |
加 |
整数,实数real即double |
整数,实数 |
|
-- |
减 |
整数,实数 |
整数,实数 |
|
* |
乘 |
整数,实数 |
整数,实数 |
|
/ |
实数除法 |
整数,实数 |
实数 |
|
div |
整数除法 |
整数 |
整数 |
|
mod |
求余 |
整数 |
整数 |
|
2.2、布尔运算符
布尔操作符不,和,或,并且异或采取任何的操作数的布尔类型并返回类型的值布尔。
布尔运算符:
操作(运算符) | 运作方式 | 操作数类型 | 结果类型 | 例 |
---|---|---|---|---|
不 not |
否定 |
布尔型 |
布尔型 |
|
和(并且) and |
连词 |
布尔型 |
布尔型 |
|
要么(或) or |
析取 |
布尔型 |
布尔型 |
|
异或 xor |
异或 |
布尔型 |
布尔型 |
|
这些操作由布尔逻辑的标准规则控制。例如,形式的表达式x and y
是真当且仅当x
是真并y
是真。
xor(异或):这个比较难理解,一句口诀:自己总结的,两个表达式比较:假真>真, 真假>真,真真>假,真值表:
(假) xor (真)=真 (真) xor (假)=真 (真) xor (真)=假
2.3、逻辑(按位)运算符
逻辑(按位)运算符:
操作(运算符) | 运作方式 | 操作数类型 | 结果类型 | 例 |
---|---|---|---|---|
不 not |
按位取反 |
整数 |
整数 |
|
和(并且) and |
按位和 |
整数 |
整数 |
|
要么 |
按位或 |
整数 |
整数 |
|
异或(或) or |
按位异或 |
整数 |
整数 |
|
shl(按位左移) |
左移:X乘以2的N层方 |
整数 |
整数 |
|
shr(按位右移) |
右移: 1、正整数Y除以2的N层方:求沿零方向四舍五入到最接近的整数的值 2、负整数Y:符号位的值替换为0 (所有负数都将符号位设置为1) |
整数 |
整数 |
|
案例: D:\delphiXEDev\JSon\UseSuperObject.dproj
procedure TfmxMain.ListBoxItem_OperatorsClick(Sender: TObject);
//<summary>基础-表达式与运算符:
var
LStrA,LStrB,LStrZ:string; LLengthStrBitwise:Integer;
begin
LStrA:='001101';
LStrB:='100001';
LStrZ:=''; LLengthStrBitwise:=0;
for LLengthStrBitwise:=1 to length(LStrB) do
LStrZ:=LStrZ+
IntToStr( StrToInt(LStrA[LLengthStrBitwise]) or StrToInt(LStrB[LLengthStrBitwise]) );
Memo1.Lines.Add(
StringOfChar(#32,6)+'二进制数:'+sLineBreak
+StringOfChar(#32,6)+'LStrA="001101"'+sLineBreak
+StringOfChar(#32,6)+'LStrB="100001"'+sLineBreak
+StringOfChar(#32,6)+'LStrA和LStrB按位or运算:'+sLineBreak
+StringOfChar(#32,6)+'(LStrA[i] or [i]),结果:'+sLineBreak
+StringOfChar(#32,6)+'LStrZ="'+LStrZ+'"'+sLineBreak
);
LStrZ:='';
for LLengthStrBitwise:=1 to length(LStrB) do
LStrZ:=LStrZ+
IntToStr( StrToInt(LStrA[LLengthStrBitwise]) and StrToInt(LStrB[LLengthStrBitwise]) );
Memo1.Lines.Add(
StringOfChar(#32,6)+'LStrA和LStrB按位and运算:'+sLineBreak
+StringOfChar(#32,6)+'(LStrA[i] and [i]),结果:'+sLineBreak
+StringOfChar(#32,6)+'LStrZ="'+LStrZ+'"'+sLineBreak
);
LStrZ:='';
for LLengthStrBitwise:=1 to length(LStrB) do
LStrZ:=LStrZ+
IntToStr( StrToInt(LStrA[LLengthStrBitwise]) xor StrToInt(LStrB[LLengthStrBitwise]) );
Memo1.Lines.Add(
StringOfChar(#32,6)+'LStrA和LStrB按位xor异或运算:'+sLineBreak
+StringOfChar(#32,6)+'(LStrA[i] xor [i]),结果:'+sLineBreak
+StringOfChar(#32,6)+'LStrZ="'+LStrZ+'"'+sLineBreak
);
end;
二进制数:
LStrA="001101"
LStrB="100001"
LStrA和LStrB按位or运算:
(LStrA[i] or [i]),结果:
LStrZ="101101"
LStrA和LStrB按位and运算:
(LStrA[i] and [i]),结果:
LStrZ="000001"
LStrA和LStrB按位xor异或运算:
(LStrA[i] xor [i]),结果:
LStrZ="101100"
shl(按位左移) shr(按位右移) :
LIntA:=80; LIntB:=3; LStrZ:='';
Memo1.Lines.Add(
StringOfChar(#32,6)+'LIntA:=80; LIntB:=3;'+sLineBreak
+StringOfChar(#32,6)+'LIntA和LIntB 按位左移shl 运算=LIntA*(2^LIntB):乘以2的N层方:'+sLineBreak
+StringOfChar(#32,6)+'( LIntA shl LIntB ),结果:'+sLineBreak
+StringOfChar(#32,6)+'LStrZ="'+IntToStr( LIntA shl LIntB )+'"'+sLineBreak
);
Memo1.Lines.Add(
StringOfChar(#32,6)+'LIntA:=80; LIntB:=3;'+sLineBreak
+StringOfChar(#32,6)+'LIntA和LIntB 按位右移shr 运算=LIntA div (2^LIntB):除以2的N层方求商:'+sLineBreak
+StringOfChar(#32,6)+'( LIntA shr LIntB ),结果:'+sLineBreak
+StringOfChar(#32,6)+'LStrZ="'+IntToStr( LIntA shr LIntB )+'"'+sLineBreak
);
LIntA:=-20; LIntB:=1; LStrZ:='';
LIntA:=LIntA shr LIntB;
LStrZ:=IntToHex(LIntA,8);
Memo1.Lines.Add(
StringOfChar(#32,6)+'LIntA:=-20; LIntB:=1;'+sLineBreak
+StringOfChar(#32,6)+'LIntA负数和LIntB 按位右移shr 运算=负整数Y:符号位的值替换为0(所有负数都将符号位设置为1):'+sLineBreak
+StringOfChar(#32,6)+'( LIntA:=LIntA shr LIntB ),结果:'+sLineBreak
+StringOfChar(#32,6)+'LIntA="'+IntToStr( LIntA shr LIntB )+'"'+sLineBreak
+StringOfChar(#32,6)+'16进制LStrZ:=IntToHex(LIntZ,8)="'+LStrZ+'"'+sLineBreak
);
LIntA:=80; LIntB:=3;
LIntA和LIntB 按位左移shl 运算=LIntA*(2^LIntB):乘以2的N层方:
( LIntA shl LIntB ),结果:
LStrZ="640"
LIntA:=80; LIntB:=3;
LIntA和LIntB 按位右移shr 运算=LIntA div (2^LIntB):除以2的N层方:求沿零方向四舍五入到最接近的整数的值:
( LIntA shr LIntB ),结果:
LStrZ="10"
LIntA:=-20; LIntB:=1;
LIntA负数和LIntB 按位右移shr 运算=负整数Y:符号位的值替换为0(所有负数都将符号位设置为1):
( LIntA:=LIntA shr LIntB ),结果:
LIntA="1073741819"
16进制LStrZ :=IntToHex(LIntA,8)="7FFFFFF6"
//LIntA初值为 negative负数, LIntA:=LIntA shr LIntB 为 positive正数.
//LStrZ的10进制数: 2147483638 = ( -LIntA shl LIntB ) =(-20 shl 1 )= 1073741819 * (2^1)
//LStrZ的16进制数: 7FFFFFF6
//LStrZ的2进制数: : 0111 1111 1111 1111 1111 1111 1111 0110
2.4、字符串运算符
关系运算符=,<>,<,>,<=和> =都采用字符串操作数(请参阅本节后面的关系运算符)。在+运算符连接两个字符串。
字符串运算符:
操作(运算符) | 运作方式 | 操作数类型 | 结果类型 | 例 |
---|---|---|---|---|
+ |
级联 |
字符串String,打包字符串packed string,字符Character |
字符串 |
|
以下规则适用于字符串连接:
- +的操作数:可以是字符串,打包字符串(Char类型的打包数组)或字符。但是,如果一个操作数的类型为WideChar,则另一个操作数必须为长字符串(UnicodeString,AnsiString或WideString)。
- +操作的结果:与任何字符串类型兼容。但是,如果操作数都是短字符串或字符,并且它们的组合长度大于255,则结果将被截断为前255个字符。
2.4、指针运算符
- 关系运算符 <,>,<= 和 > =可以采用PAnsiChar和PWideChar类型的操作数(请参阅关系运算符)。以下运算符也将指针用作操作数。有关指针的更多信息,请参见指针和指针类型(delphi)在有关数据类型(delphi)。
字符指针运算符:
操作(运算符) | 运作方式 | 操作数类型 | 结果类型 | 例 |
---|---|---|---|---|
+ |
指针加法 |
字符指针,整数 |
字符指针 |
|
- |
指针减法 |
字符指针,整数 |
字符指针,整数 |
|
右^ |
指针取消引用 |
指针 |
指针的基本类型 |
|
= |
相等 |
指针 |
布尔型 |
|
<> |
不等式 |
指针 |
布尔型 |
|
右^运算符:解除引用指针。它的操作数可以是除通用Pointer之外的任何类型的指针,通用指针必须在取消引用之前进行类型转换。
P = Q :P和Q必须都
指向相同的地址,结果才为真;否则 P <> Q
为True。
您可以使用+和-运算符来增加和减少字符指针的偏移量。您也可以使用-计算两个字符指针的偏移量之差。适用以下规则:
- 如果
I
是一个整数,并且P
是一个字符指针:1、对于PAnsiChar指针:则P + I
添加I
到P
; 给定的地址中。也就是说,它返回指向I
后面的地址的字符指针P
。(该表达式I + P
等于P + I
。)。P - I
从给定的地址中减去I
;也就是说,它返回指向之前的地址的字符指针。2、如果是PWideChar指针:P + I =
P +
I * SizeOf(WideChar)
- 如果
P
和Q
都是字符指针,则P - Q =
I
=P
(高位地址)-Q
(低位地址);也就是说,它返回一个整数I
,表示P和Q之间的字符数。
P + Q
没有定义。
2.5、集合运算符:
操作(运算符) | 运作方式 | 操作数类型 | 结果类型 | 例 |
---|---|---|---|---|
+ |
并集 |
集合 |
集合 |
|
- |
两个集合不同的部分 |
集合 | 集合 |
|
* |
两个集合交叉的部分 |
集合 | 集合 |
|
<= |
子集 |
集合 | 布尔型 |
|
> = |
超集(包含它的那个父集) |
集合 | 布尔型 |
|
= |
相等 |
集合 | 布尔型 |
|
<> |
不等 |
集合 | 布尔型 |
|
in | 包含在其中(是那个集合的成员) |
序数,集合 |
布尔型 |
|
以下规则适用于集合的 +,- ,* 运算 :
- An ordinal
O
is inX + Y
if and only ifO
is inX
orY
(or both).O
is inX - Y
if and only ifO
is inX
but not inY
.O
is inX * Y
if and only ifO
is in bothX
andY
. - The result of a +, -, or * operation is of the type
set of A..B
, whereA
is the smallest ordinal value in the result set andB
is the largest.
以下规则适用于集合的 <=, >=, =, <>, in运算 :
X <= Y
is True just in case every member ofX
is a member ofY
;Z >= W
is equivalent toW <= Z
.U = V
is True just in caseU
andV
contain exactly the same members; otherwise,U <> V
is True.- For an ordinal
O
and a setS
,O in S
is True just in caseO
is a member ofS
.
2.6、关系运算符:
关系运算符用于比较两个操作数。运算符=,<>,<=和> =也适用于集合。
仅当两个指针指向同一字符数组时,才使用运算符<,>,<=和> =比较PAnsiChar(和PWideChar)操作数。- 运算符=和<>可以采用类和类引用类型的操作数。类类型的操作数,=和<>是评估根据适用于指针的规则:
C = D
是真:C
和D必须
指向相同的实例对象,否则C <> D为
真。类引用类型的操作数,C = D
是真:表示C
和D是
相同的类,否则C <> D
为真。这种运算不会比较存储在类中的数据。有关类的更多信息,请参见类和对象(Delphi)。
2.7、类和接口运算符:
操作符as和is将类和实例对象作为操作数;以及在接口上的操作。有关更多信息,请参见类和对象(Delphi),对象接口(Delphi)和接口引用(Delphi)。
关系运算符=和<>也可对类进行运算。
2.8、@运算符:
@操作符:返回一个变量的地址,或一个函数方法,过程方法的地址; 也就是说,@构造一个指向其操作数的指针。有关指针的更多信息,请参见关于数据类型(Delphi)中的 “指针和指针类型” 。以下规则适用于@。
- 如果
X
是变量,则@X
返回的地址X
。(当X
是过程变量时,将应用特殊规则;请参阅关于数据类型(Delphi)中的 “语句和表达式中的过程类型” 。)如果默认的编译器指令有效,@X
则类型为Pointer{$T}
。在{$T+}
状态下,@X
类型为^T
,其中T
类型为X
(此区别对于分配兼容性很重要,请参阅分配兼容性)。 - 如果
F
是例程(函数或过程),则@F
返回F
的入口点(即:地址)。@F
的类型始终是Pointer。 - 当@应用于类中定义的方法时(即:类方法),该方法标识符必须使用类名限定。例如,@ TMyClass.DoSomething
注意:使用@运算符时,无法获取接口方法的地址,因为该地址在编译时未知,并且无法在运行时提取(接口:是需要去单独为它写实现的代码的)。
2.9、运算符优先级:
在复杂的表达式中,优先级规则确定执行操作的顺序。
运算符的优先级
操作(运算符) | 优先顺序 |
---|---|
@ |
第一(最高) |
* |
第二 |
+ |
第三 |
= |
第四(最低) |
2.10、函数调用:
因为函数返回值,所以函数调用是表达式。例如,如果您定义了一个函数Calc
,该函数带有两个整数参数并返回一个整数,则该函数调用Calc(24,47)
是一个整数表达式。如果I
和J
是整数变量,则I + Calc(J,8)
也是整数表达式。函数调用的示例包括:
Sum(A, 63)
Maximum(147, J)
Sin(X + Y)
Eof(F)
Volume(Radius, Height)
GetValue
TSomeObject.SomeMethod(I,J);
有关函数的更多信息,请参见过程和函数(Delphi)。
2.11、集合构造函数:
集合构造函数表示集合类型值。例如:
[5,6,7,8]
表示成员为5、6、7和8的集合。也可以这样表达集合构造函数:
[5..8]
可以表达与第1种相同的集合。
集合构造函数的语法为:
[ item1,..,itemN ]
其中每个项目要么是表示集合的基本类型的序数的表达式,要么是一对这样的表达式,它们之间有两个点(..)。当一个项目具有形式时x..y
,它是从x
到的所有序号的简写y
,包括y
;但是如果x
大于y
,则x..y
set [x..y]
表示什么也不是空集。set构造函数[ ]
表示空集,而[x]
表示其唯一成员为的值的集x
。
集合构造函数的示例:
[ red, green, MyColor ]
[ 1,5,10..(K mod 12),23,(I div 9) ]
[ 'A'..'Z','a'..'z',Chr( Digit + 48) ]
有关集合的详细信息,请参阅结构化类型(delphi)在有关数据类型(delphi)。
2.12、索引:
可为字符串,数组,数组属性以及指向字符串或数组的指针建立索引。例如,如果FileName
是字符串变量,则表达式FileName[3]
返回字符串FileName
中的第三个字符,而FileName[I + 1]
返回字符串FileName
中的第I + 1
个字符。有关字符串的信息,请参见数据类型,变量和常量。有关阵列和阵列属性的信息,请参见阵列中的数据类型,变量和常量和“ 阵列属性在” 属性(DELPHI)页。
2.13、类型转换:
有时将表达式视为属于不同类型很有用。实际上,通过类型转换,您可以通过临时更改表达式的类型来执行此操作。例如,Integer('A')
将字符强制转换A
为整数。
类型转换的语法为:
类型标识符(强制转化的表达式)
如果表达式是变量,则结果称为变量类型转换;否则,结果为值类型转换。虽然它们的语法相同,但是对于两种类型转换都适用不同的规则。
2.13.1、值类型转换:
在值类型转换中,类型标识符和强制转换表达式都必须是序数或指针类型。值类型转换的示例:
Integer('A') //ord('A') = 65 //:ASCII码值
Char(48)
Boolean(0)
Color(2)
Longint(@Buffer)
通过将括号中的表达式进行类型转换来获得结果值。如果指定类型的字节大小范围与表达式的大小不同,则可能涉及截断或扩展。表达式的符号始终被保留。
语句 :
I := Integer('A');
将Integer('A')
的值65 赋值给变量I
。
值类型转换不能带有限定符(如 ':String'),也不能出现在赋值语句的左侧。
2.13.2、变量类型转换:
您可以将任何变量强制转换为其它任何类型,只要它们的大小相同并且您不将整数与实数混合即可。(要转换数字类型,请依赖诸如Int
和的标准函数Trunc
。)变量类型转换的示例:
Char(I); Boolean(Count); TDefinedType(MyVariable);
1、变量类型转换可以出现在赋值语句的两侧 :
var MyChar:char;
//...
ShortInt(MyChar):= 122;
: 将字符 'z'
(ASCII 122)分配给MyChar
。
2、可以将变量转换为匿名函数类型。例如:
type Func = function(X: Integer): Integer;
var
F: Func;
P: Pointer;
N: Integer;
:您可以这样进行赋值:
F := Func(P); { Assign procedural value in P to F }
Func(P) := F; { Assign procedural value in F to P }
@F := P; { Assign pointer value in P to F }
P := @F; { Assign pointer value in F to P }
N := F(N); { Call function via F }
N := Func(P)(N); { Call function via P }
3、变量类型转换后还可以带有限定符,示例:
type
TByteRec = record
Lo, Hi: Byte;
end;
TWordRec = record
Low, High: Word;
end;
PByte = ^Byte;
var
B: Byte;
W: Word;
L: Longint;
P: Pointer;
begin
Memo1.Lines.Add(StringOfChar(#32,6)+'变量转换及赋值:'+sLineBreak );
W := $1234;
Memo1.Lines.Add(StringOfChar(#32,6)+W.ToString+sLineBreak );
B := TByteRec(W).Lo;
Memo1.Lines.Add(StringOfChar(#32,6)+B.ToString+sLineBreak );
TByteRec(W).Hi := 0;
Memo1.Lines.Add(StringOfChar(#32,6)+TByteRec(W).Hi.ToString+sLineBreak );
L := $1234567;
Memo1.Lines.Add(StringOfChar(#32,6)+L.ToString+sLineBreak );
W := TWordRec(L).Low;
Memo1.Lines.Add(StringOfChar(#32,6)+W.ToString+sLineBreak );
B := TByteRec(TWordRec(L).Low).Hi;
Memo1.Lines.Add(StringOfChar(#32,6)+B.ToString+sLineBreak );
B := PByte(L)^;
Memo1.Lines.Add(StringOfChar(#32,6)+B.ToString+sLineBreak );
end;
在此示例中,TByteRec
用于访问单词的低位和高位字节,并TWordRec
访问长整数的低位和高位字。你可以调用预先定义的功能Lo
和Hi
为了同样的目的,但一个变量的类型转换具有可以在赋值语句的左侧使用的优势。 结果:
变量转换及赋值:
4660
52
0
19088743
17767
69
97
有关类型转换指针的信息,请参见指针和指针类型(Delphi)。有关强制转换类和接口类型的信息,请参见类参考和接口参考(Delphi)中的 “ as运算符” 。