Delphi 10.3 函数 CharUpper 和 CharUpperW 不同 Delphi 10.4
Delphi 10.3 functions CharUpper and CharUpperW differ Delphi 10.4
有人知道 Delphi 10.3 中的 CharUpper
和 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...
Delphi 10.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”!
var
char , chr : WideChar;
begin
chr := 'a';
char := WideChar(CharUpperW(PWideChar(chr)));
end;
此示例在 10.4 下无法正常工作,输出是随机字符。
当然...
函数声明 CharUpperW
与 Delphi.
的boath版本相同
LPWSTR = PWideChar;
function CharUpperW(lpsz: LPWSTR): LPWSTR; stdcall;**
编辑:在 10.4
下添加了反汇编代码
umCommon.pas.114: chr := 'a';
0064C52C 66BB6100 mov bx,[=16=]61
umCommon.pas.115: char := WideChar(CharUpperW(PWideChar(chr)));
0064C530 8D45FC lea eax,[ebp-]
0064C533 8BD3 mov edx,ebx
0064C535 E8EEE7DBFF call @UStrFromWChar
0064C53A 8B45FC mov eax,[ebp-]
0064C53D E8C2E7DBFF call @UStrToPWChar
0064C542 50 push eax
0064C543 E8809DDCFF call CharUpperW
10.3下的反汇编代码
umCommon.pas.114: chr := 'a';
0063A905 66BB6100 mov bx,[=17=]61
umCommon.pas.115: char := WideChar(CharUpperW(PWideChar(chr)));
0063A909 0FB7C3 movzx eax,bx
0063A90C 50 push eax
0063A90D E8AAB1DDFF call CharUpperW
Win32 CharUpperW()
函数不接受单个 WideChar
作为输入,只有 PWideChar
。但是该指针的 解释 取决于它的 high-order 字是零(low-order 字包含单个字符)还是 non-zero (整个指针指向 null-terminated 字符串)。
CharUpperW(WideChar('a'))
甚至可以在任何版本中编译的唯一方法是,如果 Embarcadero 添加了他们自己的重载,将单个 WideChar
作为输入(我没有任何 10.x 已安装版本以验证)。
恕我直言,使用 CharUpperW()
有点危险,因为它滥用了指针。我不相信它带有类型转换的文字,而是使用一个变量,这样你就可以确保你给它的正是它真正想要的:
var
chr : array[0..1] of WideChar;
begin
chr[0] := 'a';
chr[1] := #0;
CharUpperW(chr);
end;
var
chr : WideChar;
begin
chr := 'a';
char := WideChar(CharUpperW(PWideChar(chr)));
end;
也就是说,RTL 中还有其他函数可以处理此任务,请改用这些函数。
更新: 我为此创建了支持票:
自从 Delphi 10.4 创建隐藏字符串并且 CharUpperW
在与 single-char 或 null-terminated 字符串输入一起使用时充当 different,您需要重写您的使其与 10.4 和 10.3(及更早)版本一致的代码:
var
s: string;
begin
s := 'a';
CharUpperW(@s[1]);
end;
P.S。由于这些困难,我建议您使用 System.SysUtils.
中的 UpperCase
/ AnsiUpperCase
好的,在你的帮助下我找到了答案......
实际上,函数 CharUpper
和 CharUpperW
在 Winapi.Windows
单元中,并且都调用相同的 API 调用 CharUpperW
。
但是在 Delphi 版本 10.4 中单元 Winapi.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;
编译器采用这个重载函数而不是旧函数,结果在我的问题中有描述。
为了避免这个重载函数,我们必须更正类型转换变量 Chr
以获得正确的结果:
var
Chr :Char; //Or WideChar
begin
Chr := 'a';
Chr := Char(CharUpper(LPWSTR(ord(Chr))));
编辑:我们也可以像这样调用 CharUpperW API 函数:
var
Chr :WideChar; //or Char
begin
Chr := 'a';
Chr := Char(CharUpper(LPWSTR(ord(Chr))));
反汇编代码相同:
umCommon.pas.109: Chr := 'a';
0063A906 66BB6100 mov bx,[=13=]61
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
有人知道 Delphi 10.3 中的 CharUpper
和 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...
Delphi 10.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”!
var
char , chr : WideChar;
begin
chr := 'a';
char := WideChar(CharUpperW(PWideChar(chr)));
end;
此示例在 10.4 下无法正常工作,输出是随机字符。
当然...
函数声明 CharUpperW
与 Delphi.
LPWSTR = PWideChar;
function CharUpperW(lpsz: LPWSTR): LPWSTR; stdcall;**
编辑:在 10.4
下添加了反汇编代码umCommon.pas.114: chr := 'a';
0064C52C 66BB6100 mov bx,[=16=]61
umCommon.pas.115: char := WideChar(CharUpperW(PWideChar(chr)));
0064C530 8D45FC lea eax,[ebp-]
0064C533 8BD3 mov edx,ebx
0064C535 E8EEE7DBFF call @UStrFromWChar
0064C53A 8B45FC mov eax,[ebp-]
0064C53D E8C2E7DBFF call @UStrToPWChar
0064C542 50 push eax
0064C543 E8809DDCFF call CharUpperW
10.3下的反汇编代码
umCommon.pas.114: chr := 'a';
0063A905 66BB6100 mov bx,[=17=]61
umCommon.pas.115: char := WideChar(CharUpperW(PWideChar(chr)));
0063A909 0FB7C3 movzx eax,bx
0063A90C 50 push eax
0063A90D E8AAB1DDFF call CharUpperW
Win32 CharUpperW()
函数不接受单个 WideChar
作为输入,只有 PWideChar
。但是该指针的 解释 取决于它的 high-order 字是零(low-order 字包含单个字符)还是 non-zero (整个指针指向 null-terminated 字符串)。
CharUpperW(WideChar('a'))
甚至可以在任何版本中编译的唯一方法是,如果 Embarcadero 添加了他们自己的重载,将单个 WideChar
作为输入(我没有任何 10.x 已安装版本以验证)。
恕我直言,使用 CharUpperW()
有点危险,因为它滥用了指针。我不相信它带有类型转换的文字,而是使用一个变量,这样你就可以确保你给它的正是它真正想要的:
var
chr : array[0..1] of WideChar;
begin
chr[0] := 'a';
chr[1] := #0;
CharUpperW(chr);
end;
var
chr : WideChar;
begin
chr := 'a';
char := WideChar(CharUpperW(PWideChar(chr)));
end;
也就是说,RTL 中还有其他函数可以处理此任务,请改用这些函数。
更新: 我为此创建了支持票:
自从 Delphi 10.4 创建隐藏字符串并且 CharUpperW
在与 single-char 或 null-terminated 字符串输入一起使用时充当 different,您需要重写您的使其与 10.4 和 10.3(及更早)版本一致的代码:
var
s: string;
begin
s := 'a';
CharUpperW(@s[1]);
end;
P.S。由于这些困难,我建议您使用 System.SysUtils.
中的UpperCase
/ AnsiUpperCase
好的,在你的帮助下我找到了答案......
实际上,函数 CharUpper
和 CharUpperW
在 Winapi.Windows
单元中,并且都调用相同的 API 调用 CharUpperW
。
但是在 Delphi 版本 10.4 中单元 Winapi.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;
编译器采用这个重载函数而不是旧函数,结果在我的问题中有描述。
为了避免这个重载函数,我们必须更正类型转换变量 Chr
以获得正确的结果:
var
Chr :Char; //Or WideChar
begin
Chr := 'a';
Chr := Char(CharUpper(LPWSTR(ord(Chr))));
编辑:我们也可以像这样调用 CharUpperW API 函数:
var
Chr :WideChar; //or Char
begin
Chr := 'a';
Chr := Char(CharUpper(LPWSTR(ord(Chr))));
反汇编代码相同:
umCommon.pas.109: Chr := 'a';
0063A906 66BB6100 mov bx,[=13=]61
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