CharUpper
有人知道 Delphi 10.3 中的声明与CharUpperW
Delphi 10.4 中不同的原因吗?
Delphi 10.3 中的正确声明
var
chr :WideChar;
begin
chr := WideChar(CharUpperW(PWideChar('a'))); //chr = 'A'
// chr := WideChar(CharUpperW(WideChar('a'))); //raise exeption: "access violation...
Run Code Online (Sandbox Code Playgroud)
Delphi 10.4 中的正确声明
var
chr :WideChar;
begin
// chr := WideChar(CharUpperW(PWideChar('a'))); //raise exeption: "access violation...
chr := WideChar(CharUpperW(WideChar('a'))); //chr = 'A'
Run Code Online (Sandbox Code Playgroud)
编辑:Remy Lebeau 对 PWideChar 的解释是正确的,但 Delphi 10.4 版和更早版本仍然存在差异!
Lebeau解释代码示例在10.4版本及更早版本中编译,但函数的输出不同。10.4 之前的所有版本都得到正确的输出“A”!
var
char , chr : WideChar;
begin
chr := 'a';
char := WideChar(CharUpperW(PWideChar(chr)));
end;
Run Code Online (Sandbox Code Playgroud)
10.4 下的此示例无法正常工作,输出是随机字符。
当然...函数的声明CharUpperW
在Delphi的Boath版本中是相同的。
LPWSTR = PWideChar;
function CharUpperW(lpsz: LPWSTR): LPWSTR; stdcall;**
Run Code Online (Sandbox Code Playgroud)
编辑:在 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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
GJ.*_*GJ. -1
好的,在您的帮助下,我找到了答案...实际上,函数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;
Run Code Online (Sandbox Code Playgroud)
编译器采用此重载函数而不是旧函数,结果在我的问题中进行了描述。
为了避免这种重载函数,我们必须更正类型转换变量Chr
以获得正确的结果:
var
Chr :Char; //Or WideChar
begin
Chr := 'a';
Chr := Char(CharUpper(LPWSTR(ord(Chr))));
Run Code Online (Sandbox Code Playgroud)
编辑:我们还可以调用 CharUpperW API 函数,例如:
var
Chr :WideChar; //or Char
begin
Chr := 'a';
Chr := Char(CharUpper(LPWSTR(ord(Chr))));
Run Code Online (Sandbox Code Playgroud)
反汇编后的代码是一样的:
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
Run Code Online (Sandbox Code Playgroud)