The Delphi Bug List

Entry No.
660
コンパイラ - コンパイル出来ない
SetString は、その "buffer" 引数に型無しポインタを受け付けない
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 4.03 5.0 5.01 6.0 6.01 6.02 Kylix 1.0
N/A Exists Exists Exists Exists Exists Exists Exists Exists Exists Exists Exists Unknown Unknown Exists
解説
Reported by Arsene von Wyss; checked by Jordan Russell
var
  S: string;
  C: PChar;
  P: Pointer;
begin
  SetString(S,C,1);
  SetString(S,P,1);
end;
二番目の SetString でコンパイラは、"互換性の無い型です" のエラーを出力して止まります。コンパイラは PChar の代用として型無しポインタを受け付けません。

さらに奇妙なことに、次のコードは受け入れられます:
  SetString(S,nil,1);

私はこれをバグに分類したいです。なぜなら Delphi のヘルプは、その "型の互換性"において、型無しポインタは任意のポインタ型(PChar を含む)に割り当て可能であると述べているからです。
解決策 / 回避方法
ポインタを PChar に型キャストしてください:
  SetString(S,PChar(P),1);
ユーザーからのコメント
Brad Stowers
25 Apr 2001  01:23 PM GMT
これに関連する奇妙なこと:

SetString と同じ引数を持つプロシージャを自分で宣言した場合、それは型無しポインタを受け付けます。System.pas の SetString を調べたところ、私はその宣言が非常に奇妙であることを発見しました:

{ Procedures and functions that need compiler magic }
{...many declarations snipped...}
procedure _SetString{var s: ShortString: buffer: PChar; len: Integer};

ここで少し注意して欲しいことがあります。これは、"コンパイラマジック" と呼ばれるものを必要とする宣言のグループの中にリストされています。引数リストはコメントで囲まれており、あなたが期待するように括弧では囲まれていません(これは前述のコンパイラマジックに関連するのだと思います)。そして ShortString の型の後にセミコロンではなく、コロンがあることに注意して下さい。このような宣言は他にはありませんので、私は、これは誰かがタイプミスをして、実際にはコンパイルされないためにそれが受け入れられたのだろうと思います。これこそコンパイラのマジックです。私は、このコロンがセミコロンなら全てが期待通りに動作するだろうと確信しています。
Arsene von Wyss
29 Apr 2001  01:12 PM GMT
コメントありがとうございます。コンパイラマジックを必要とするシステムルーチンに伴う行為とは、その引数がコンパイラマジックの影響下で宣言されるというものです。実際のところコメント内の引数は SYSTEM.PAS を見る人のためのものであって、コンパイラによって解析されることは一切ありません(そのため、タイプミスがあってもこの問題への影響はありません)。Write/Read 等いくつかのプロシージャは、有効な Delphi の Object pascal 文法を使って宣言することが出来ない引数を受け入れることに注意して下さい。

SetString のコンパイラマジック宣言は間違っているのだろうと思います。そしてこれは簡単には変更できません。それは完全にコンパイラに統合されています。実際のところ、コンパイラによって置き換えられる五種類の異なる SetString プロシージャが存在します。ひとつは short string 用、二つは ANSI string 用、残り二つは wide string 用です。

それらは以下の通りです:
* SetString (実際に目にするもの)
* LStrFromPCharLen
* LStrFromPWCharLen
* WStrFromPCharLen
* WStrFromPWCharLen

ShortString を取る SetString に PWideChar を使用することは出来ませんが、ANSIString と WideString は互いの種類の PChar を受け入れることに注意して下さい。これはある程度このバグを説明してくれます:コンパイラは扱っている PChar の正確な型を知ろうとし、PChar (あるいは、PChar や PWideChar として常に有効な nil )以外は受け付けないという事です。しかしながら引数として型無しポインタが与えられた場合、ANSIString を取る SetString なら PChar だとみなし、WideString を取る SetString なら PWideChar だとみなすことは、安全な仮定だと思います。
Hallvard Vassbotn
30 Aug 2001  08:26 AM GMT
私の考えとしては、これはバグではなく混乱の元(gotcha)にすべきだと思います。
Latest update of this entry: 2001-06-18
本家 The Delphi Bug List のエントリーはこちら
The Delphi Bug List 日本語訳 へ