Delphi中的Char和Chr
在转换类型时使用Chr和Char的区别在于一个是函数,另一个是强制转换 所以:Delphi中的Char和Chr,delphi,char,Delphi,Char,在转换类型时使用Chr和Char的区别在于一个是函数,另一个是强制转换 所以:Char(66)=Chr(66) 我不认为有任何性能差异(至少我从未注意到任何差异,一个可能会调用另一个)。。。。我确信有人会纠正我的错误 编辑感谢Ulrich的测试,证明它们实际上是相同的。 编辑2是否有人能想到它们可能不完全相同的情况,例如,由于上下文关系,您被迫使用其中一种 您在代码中使用了哪一种?为什么?Chr是函数调用,它比类型转换要贵一点。但我认为Chr是由编译器内联的 我在D2007中做了一个小测试: p
Char(66)=Chr(66)
我不认为有任何性能差异(至少我从未注意到任何差异,一个可能会调用另一个)。。。。我确信有人会纠正我的错误
编辑感谢Ulrich的测试,证明它们实际上是相同的。编辑2是否有人能想到它们可能不完全相同的情况,例如,由于上下文关系,您被迫使用其中一种
您在代码中使用了哪一种?为什么?Chr是函数调用,它比类型转换要贵一点。但我认为Chr是由编译器内联的 我在D2007中做了一个小测试:
program CharChr;
{$APPTYPE CONSOLE}
uses
Windows;
function GetSomeByte: Byte;
begin
Result := Random(26) + 65;
end;
procedure DoTests;
var
b: Byte;
c: Char;
begin
b := GetSomeByte;
IsCharAlpha(Chr(b));
b := GetSomeByte;
IsCharAlpha(Char(b));
b := GetSomeByte;
c := Chr(b);
b := GetSomeByte;
c := Char(b);
end;
begin
Randomize;
DoTests;
end.
两个调用产生相同的汇编代码:
CharChr.dpr.19: IsCharAlpha(Chr(b));
00403AE0 8A45FF mov al,[ebp-$01]
00403AE3 50 push eax
00403AE4 E86FFFFFFF call IsCharAlpha
CharChr.dpr.21: IsCharAlpha(Char(b));
00403AF1 8A45FF mov al,[ebp-$01]
00403AF4 50 push eax
00403AF5 E85EFFFFFF call IsCharAlpha
CharChr.dpr.24: c := Chr(b);
00403B02 8A45FF mov al,[ebp-$01]
00403B05 8845FE mov [ebp-$02],al
CharChr.dpr.26: c := Char(b);
00403B10 8A45FF mov al,[ebp-$01]
00403B13 8845FE mov [ebp-$02],al
编辑:修改样本以缓解Nick的担忧
编辑2:尼克的愿望是我的命令。;-)
chr
是一个函数,因此它返回类型为char
的新值
char(x)
是一个强制转换,这意味着实际的x
对象被用作不同的类型
许多系统功能,如inc、dec、chr、ord都是内联的
char
和chr
都很快。每次使用最合适的一个,并且更好地反映您想要执行的操作。帮助说明:Chr返回带有字节类型表达式X的序号值(ASCII值)的字符* 那么,一个字符在计算机内存中是如何表示的呢?猜猜看,作为一个字节*。事实上,Chr和Ord函数仅适用于Pascal,因为Pascal是一种严格类型化的语言,禁止在请求字符时使用字节*。对于计算机来说,生成的字符仍然表示为字节*-那么它将转换成什么?实际上,这个函数调用没有发出任何代码,就像类型转换没有省略任何代码一样。因此:没有区别 为了避免类型转换,您可能更喜欢
chr
注意:类型转换不能与显式类型转换混淆!在Delphi2010中,编写类似于Char(a)
的东西,而a是AnsiChar,实际上会做一些事情
**对于Unicode,请将字节替换为整数*
编辑:
仅举一个例子(假设非Unicode):
生成类似的代码
ftest.pas.46: a := 60;
0045836D C645FB3C mov byte ptr [ebp-$05],$3c
ftest.pas.47: c := Chr(60);
00458371 C645FA3C mov byte ptr [ebp-$06],$3c
ftest.pas.48: c := Chr(a);
00458375 8A45FB mov al,[ebp-$05]
00458378 8845FA mov [ebp-$06],al
ftest.pas.49: b := a;
0045837B 8A45FB mov al,[ebp-$05]
0045837E 8845F9 mov [ebp-$07],al
将字节分配给字节实际上与通过CHR()将字节分配给字符是相同的。它们是相同的,但不必相同。不要求字符的内部表示形式与其序号值一一对应。没有任何规定表明,持有值
'a'
的Char
变量必须持有数值65。要求是,当您对该变量调用Ord
时,结果必须是65,因为这是程序字符编码中为字母A指定的代码点
当然,实现该要求的最简单方法是让变量也保持数字值65。因此,函数调用和类型转换总是相同的
如果实现不同,那么当您调用Chr(65)
时,编译器将查找代码点65处的字符并将其用作结果。当您编写Char(65)
时,只要存储在内存中的数字结果是65,编译器就不会担心它真正代表什么字符
这是在吹毛求疵吗?是的,绝对如此,因为在所有当前的实现中,它们都是相同的。我把这比作空指针是否一定为零的问题。不是,但在所有实现中,它都是这样结束的。chr是类型安全的,char不是:尝试编写
chr(256)
,您将得到一个编译器错误。尝试对字符(256)进行编码,您将获得序号值为0或1的字符,具体取决于计算机内部的整数表示形式
我将在上面加上后缀,表示这适用于unicode之前的Delphi。我不知道chr和char是否已经更新为考虑unicode。这似乎是作弊。尝试使用变量而不是常量。如果你得到同样的结果,我会给你的答案加1,如果你测试
ch:=chr(b);ch:=char(b)代码>这将是完美的。如果它们都相同。。。(他们似乎是这样的),那么你怎么能判断哪一个是合适的呢,这更像是“你当时喜欢哪一个”?@JamesB,我没说他们是一样的chr
是一个函数。但在大多数情况下,它们可以被视为相同的。Chr不返回新值,而是返回作为参数给定的表达式的结果。在调用chr之前对表达式求值,而对chr的调用完全没有任何作用。@Uwe Raabe,可以,但该临时值(表达式的求值)是返回值,否?它们大部分是内置的,因为在系统单元中没有对它们的定义。与单纯的内联函数稍有不同。使用Char而不是Chr的一种情况是,如果您正在进行显式转换,例如从AnsiChar进行转换。。感谢Uwe RaabeIt,它看起来像是一个重复功能的案例,可能是因为历史原因。类似于“原始版本被称为Chr(),但后来有人说,如果我们称它为Char(),这会更有意义,因为它基本上是一个字符的类型转换,但我们不能更改它,因为有很多现有代码使用Chr(),这会破坏它,所以我们将把它们都放进去。”这只是一个猜测,但这可能与实际情况非常接近。Jensen/Wirth的原始Pascal已经有了一个Chr()函数,但没有类型强制转换。它们不适合语言设计。我知道,字符只是一个例子。ORD()还将仅返回内部整数表示形式
ftest.pas.46: a := 60;
0045836D C645FB3C mov byte ptr [ebp-$05],$3c
ftest.pas.47: c := Chr(60);
00458371 C645FA3C mov byte ptr [ebp-$06],$3c
ftest.pas.48: c := Chr(a);
00458375 8A45FB mov al,[ebp-$05]
00458378 8845FA mov [ebp-$06],al
ftest.pas.49: b := a;
0045837B 8A45FB mov al,[ebp-$05]
0045837E 8845F9 mov [ebp-$07],al