質問

Delphi 2009 を入手したところですが、Unicode 文字列への切り替えにより必要になる可能性のある変更について以前にいくつかの記事を読みました。主に、sizeof(char) が 1 であることが保証されなくなったと述べられています。しかし、これが文字列操作に関して興味深いのはなぜでしょうか?

たとえば、AnsiString:='Test' を使用し、String (現在は Unicode) で同じことを行うと、Length() = 4 が得られます。これはどちらの場合も正しい値です。テストしたわけではありませんが、他のすべての文字列操作関数も同じように動作し、引数が Unicode 文字列であるかそれ以外であるかを内部で決定していると確信しています。

文字列操作を行う場合、char の実際のサイズが重要になるのはなぜですか?(もちろん、文字列を文字列として使用し、他のデータを保存しない場合)

助けてくれてありがとう!ホルガー

役に立ちましたか?

解決

ユニコードあり SizeOf(SomeChar) <> 長さ(SomeChar). 。基本的に長さは サイズの合計より小さいです 文字s.想定しない限り SizeOf(Char) = 1, 、 または SizeOf(SomeString[x]) = 1 (どちらもそうなので 間違い 今)または交換してみてください バイトと一緒です 文字なら、何も問題はないはずです。何か創造的なことをしている場所ならどこでも バイトに入る シャアまたは s、その場合は使用する必要があります AnsiString.

(SizeOf(SomeString) は、本質的にコンパイラの魔法を備えたポインタであるため、長さに関係なく 4 のままです。)

他のヒント

古い Delphi コードでは、深く考えずに暗黙的に文字からバイトに変換することがよくあります。たとえば、ストリームに書き込む場合などです。ストリームに文字列を書き込むときは、書き込むバイト数を指定する必要がありますが、代わりに文字数を渡すことがよくあります。見る Chris Bensen からのこの投稿 別の例として。

この暗黙的な変換や古いコードを行うもう 1 つの方法は、「文字列」を使用してバイナリ データを保存することです。この場合、実際にはバイトが必要ですが、データ型では文字が必要です。D2009 には これに適したタイプ.

Delphi 2009 は試しませんでしたが、Unicode への切り替えが遅い fpc を使用しています。以下のすべてが Delphi 2009 にも当てはまると 95% 確信しています。

fpc (Unicode をサポートする場合) では、「length」のような関数でコードページが考慮されるようになります。したがって、「人間」が認識する文字列の長さを返します。たとえば、中国語の文字が 2 つあり、どちらも Unicode で 2 バイトのメモリを必要とする場合、文字列には 2 つの文字があるため、length は 2 を返します。ただし、文字列には 4 バイトのメモリが必要です。(+ 参照カウントと先頭 #0 のメモリが必要ですが、それはさておき)

もうできないことは次のとおりです。

var p : pchar;
begin
  p := s[1];
  for i := 0 to length(string)-1 do
    begin
    write(p);
    inc(p);
    end;      
end;

なぜなら、このコードは、2 つの漢字の例では、間違った 2 文字を書き込むことになるからです。つまり、最初の「実際の」文字の一部である 2 バイトです。

要するに:Length() は、文字列に割り当てられたバイト数を返すのではなく、文字数を返します。(Unicode に切り替える前は、これら 2 つの値は互いに同じでした)

バイトレベルで操作を行っていない限り、文字の実際のサイズは問題になりません。

(もちろん、文字列を文字列として使用し、他のデータを保存しない場合)

それが重要なポイントです。あなたは他の目的で文字列を使用しませんが、一部の人々は使用します。彼らは文字列を配列と同じように使用するので、彼ら (そして私も含めて) がそのような使用法をすべてチェックして、何も壊れていないことを確認する必要があります...

この変換が実際には望ましくない場合があることを忘れないでください。たとえば、レコードに GUID を保存する場合を考えてみましょう。GUID には 16 進文字と - および括弧のみを含めることができます。これらの文字が 2 倍のスペースを占有すると、既存のコードに大きな影響を与える可能性があります。確かに、簡単な解決策は、それらを AnsiString に変更し、文字列操作を行った場合にコンパイラの警告に対処することです。

Windows API 呼び出しを行う場合、問題が発生する可能性があります。または、そのようなレガシーコードがある場合は、 株式会社 または 12月str[0] 長さを変更します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top