Delphi 10.3函数CharUpper和CharUpper与Delphi 10.4不同
有人知道Delphi10.3中的Delphi 10.3函数CharUpper和CharUpper与Delphi 10.4不同,delphi,Delphi,有人知道Delphi10.3中的CharUpper和CharUpper声明与Delphi10.4中的声明不同的原因吗 Delphi10.3中的正确声明 var chr :WideChar; begin chr := WideChar(CharUpperW(PWideChar('a'))); //chr = 'A' // chr := WideChar(CharUpperW(WideChar('a'))); //raise exept
CharUpper
和CharUpper
声明与Delphi10.4中的声明不同的原因吗
Delphi10.3中的正确声明
var
chr :WideChar;
begin
chr := WideChar(CharUpperW(PWideChar('a'))); //chr = 'A'
// chr := WideChar(CharUpperW(WideChar('a'))); //raise exeption: "access violation...
Delphi10.4中的正确声明
var
chr :WideChar;
begin
// chr := WideChar(CharUpperW(PWideChar('a'))); //raise exeption: "access violation...
chr := WideChar(CharUpperW(WideChar('a'))); //chr = 'A'
编辑:Remy Lebeau对PWideChar的解释是正确的,但Delphi 10.4版和早期版本仍然存在差异
Lebeau expalation代码示例在版本10.4和早期版本中编译,但函数的输出不同。10.4之前的所有版本都获得了正确的输出“A”
10.4下的此示例无法更正输出为随机字符
当然。。。
函数的声明在Delphi的boath版本中是相同的
LPWSTR = PWideChar;
function CharUpperW(lpsz: LPWSTR): LPWSTR; stdcall;**
编辑:在10.4中添加反汇编代码
umCommon.pas.114: chr := 'a';
0064C52C 66BB6100 mov bx,$0061
umCommon.pas.115: char := WideChar(CharUpperW(PWideChar(chr)));
0064C530 8D45FC lea eax,[ebp-$04]
0064C533 8BD3 mov edx,ebx
0064C535 E8EEE7DBFF call @UStrFromWChar
0064C53A 8B45FC mov eax,[ebp-$04]
0064C53D E8C2E7DBFF call @UStrToPWChar
0064C542 50 push eax
0064C543 E8809DDCFF call CharUpperW
10.3下的反汇编代码
umCommon.pas.114: chr := 'a';
0063A905 66BB6100 mov bx,$0061
umCommon.pas.115: char := WideChar(CharUpperW(PWideChar(chr)));
0063A909 0FB7C3 movzx eax,bx
0063A90C 50 push eax
0063A90D E8AAB1DDFF call CharUpperW
Win32CharUpperW()
函数不接受单个WideChar
作为输入,只接受一个PWideChar
。但该指针的解释取决于其高阶字是零(低阶字包含一个字符)还是非零(整个指针指向以null结尾的字符串)
CharUpperW(WideChar('a'))
甚至可以在任何版本中编译的唯一方法是,Embarcadero添加了自己的重载,将单个WideChar
作为输入(我没有安装任何10.x版本来验证)
总之,CharUpperW()
使用起来有点危险,因为指针被滥用了。对于类型转换的文本,我不相信它,而是使用变量,这样您可以确保您给出的正是它真正想要的:
var
chr:WideChar的数组[0..1];
开始
chr[0]:=“a”;
chr[1]:=#0;
查沃(chr);
结束;
var
chr:WideChar;
开始
chr:='a';
char:=WideChar(CharUpperW(PWideChar(chr));
结束;
也就是说,RTL中还有其他函数来处理此任务,请改用这些函数
更新:我已为此创建了支持票证:
由于Delphi 10.4创建隐藏字符串,并且当它与单个字符或以null结尾的字符串输入一起工作时,
charupper w
会起作用,因此您需要重写代码,使其与10.4和10.3(及更早版本)的代码保持一致:
var
s: string;
begin
s := 'a';
CharUpperW(@s[1]);
end;
另外,由于这些困难,我建议您使用System.SysUtils中的
大写
/AnsiUpperCase
。好的,在您的帮助下,我找到了答案。。。
实际上,函数CharUpper
和CharUpperW
位于Winapi.Windows
单元中,它们都调用相同的API调用CharUpperW
。
但是在Delphi 10.4版的unitWinapi.Windows
中出现了新的函数重载:
function CharUpper(lpsz: LPWSTR): LPWSTR; overload; stdcall; external user32kernel name 'CharUpperW';
function CharUpper(tch: WideChar): WideChar; overload; stdcall;
begin
Result := WideChar(IntPtr(CharUpperW(LPWSTR(IntPtr(tch)))));
end;
编译器使用这个重载函数而不是旧函数,结果在我的问题中描述
为了避免此重载函数,我们必须更正typecast变量Chr
,以获得正确的结果:
var
Chr :Char; //Or WideChar
begin
Chr := 'a';
Chr := Char(CharUpper(LPWSTR(ord(Chr))));
编辑:我们也可以调用Charupper API函数,如:
var
Chr :WideChar; //or Char
begin
Chr := 'a';
Chr := Char(CharUpper(LPWSTR(ord(Chr))));
反汇编代码相同:
umCommon.pas.109: Chr := 'a';
0063A906 66BB6100 mov bx,$0061
umCommon.pas.110: Chr := Char(CharUpperW(LPWSTR(ord(Chr))));
0063A90A 0FB7C3 movzx eax,bx
0063A90D 50 push eax
0063A90E E8A9B1DDFF call CharUpperW
0063A913 8BD8 mov ebx,eax
你能比较10.3和10.4(单位Winapi.Windows.pas)中
CharUpperW的声明吗?@zed 10.3和10.4中CharUpperW的声明是相同的!LPWSTR=PWideChar;函数CharUpperW(lpsz:LPWSTR):LPWSTR;stdcall;10.4从单个字符生成隐藏字符串,并将指向该字符串的指针放在CharUpperW上,然后将其全部关闭。Delphi 10.3中没有重载版本的CharUpperW
,但两个变体都编译成功。另外,看看这个反汇编代码:-编译器将char值放在堆栈上,而不是指针上。当我们使用WideChar('a')
调用函数时,它将指针置于适当的位置,这将导致AV。这一切意味着什么?很抱歉,但是您的WideChar第二个示例代码在版本10.4中得到的输出仍然与早期版本的Delphi不同。检查我的答案是否正确…我理解。10.3工作正常-它为PWideChar('a')
输入单个字符值,或为宽字符串输入输入指针。这正是我们所需要的@GJ你能看看10.4下的反汇编代码吗?我认为编译器使用单字符输入时出错了。@GJ您不应该编辑答案,而是将其添加到您的问题中。对不起,我知道。。。我要快速按Remy Lebeau编辑,而不是我的。。。CorectedYeah<代码>大写
/AnsiUpperCase
出于我的目的会变慢。@s[1]
与执行PChar(s)相同@RemyLebeau它不是。在第一种情况下,编译器调用UniqueStringU
,一切正常;在第二种情况下,它调用UStrToPWChar
,并发生AV。@GJ。“UpperCase
/AnsiUpperCase
对我来说太慢了”-你试过了吗?@Remy Lebeau。不,我使用的是upcase table:UpCaseTable:Char的数组[Char];wich在程序开始时填充。函数CharUpper
和重载无关,但typecastord(Chr)
do。再次打开反汇编代码,看看会发生什么。@zed right和typecasted也必须是CharUpper
函数,正确答案。反汇编后的代码现在是相同的<代码>编译器使用这个重载函数,而不是旧的-不,它错了!在您的示例代码中,您直接调用CharUpperW
,所以编译器并没有使用任何重载。由于编译器的新行为而发生错误。使用ord
添加类型转换时,您强制新编译器的行为与以前的一样。@zed没有任何函数charuperw
和charuper
是相同的!检查unitWinapi.Windows
中的函数CharUpperW
也被重载!我没有10.4。如果CharUpperW
以相同的方式重载,则可以像Chr:=CharUpperW(Chr)一样使用它代码>不是吗?
umCommon.pas.109: Chr := 'a';
0063A906 66BB6100 mov bx,$0061
umCommon.pas.110: Chr := Char(CharUpperW(LPWSTR(ord(Chr))));
0063A90A 0FB7C3 movzx eax,bx
0063A90D 50 push eax
0063A90E E8A9B1DDFF call CharUpperW
0063A913 8BD8 mov ebx,eax