背景情報については、この質問を参照してください。
TDigits = AnsiString; //Should be `= array of NativeUInt`, but string has COW
TBigint = record
Digit: TDigits; // Unsigned number, LSB stored in D[0], MSB in D[size-1]
Size: Byte; // Mininum = 4, maximum 127.
MSI: Byte; // Most significant (native)integer minimum=1, maximum=127
Sign: Shortint;
class operator Implicit(a: Integer): TBigint;
背景
私は (ほぼ) 通常の整数のように動作する bignum クラスを使用しています。
したがってa:= 1000000*10000000*12000000*10000000*1000000;
、完全に有用な結果が得られます。この目的のために、 のレコードを使用しclass operators
ます。これらは、自動型変換と初期化をトリガーします。aを別の に割り当てているため、変換がない場合を
除きます。 TBigint
TBigint
ソリューション
Ansistring を使用してコア データを保存します。コピー オン ライトがあり、必要に応じて自身のクローンを作成します。
問題: (文字列を変更していることを Delphi が認識しない場合、COW は機能しません)として偽装され
た Digit を操作する純粋なアセンブラ ルーチンがいくつかあります。 dynamic array
Ansistring
ただし、次のようなことをすると:
Label1.Caption:= BigintToStr(b);
..... this fires:
function BigintToStr(const X: TBigint): AnsiString;
var
..
LocX:= x; <<-- assignment, locX and X are joined at the hip.
repeat
D := DivBigint(LocX, 1000000000, LocX); <<-- this routine changes LocX
^^+-- but assembler routines bypass COW
X
股関節が関節でLocX
、一方に何が起こっても他方に起こります。明らかに、Delphi は asm ルーチンが変更
されていることを認識していないため、COW が適切です。DivBigint
LocX
ルーチンを次のように変更した場合の回避策:
function BigintToStr(const X: TBigint): AnsiString;
var
..
LocX:= x;
LocX.Digit[2]:= #0; <<-- inconsequential change to force COW.
repeat
D := DivBigint(LocX, 1000000000, LocX);
Delphi はすべて手がかりをつかみ、問題なく動作します。
LocX
リンクが解除され、X
すべて正常に動作します。
ただし、空きスペースの途中でばかげた変更を加えたくありません。
文字列でトリガーCOWを強制する適切な/適切な/公式*の方法はありますか?
システムコールのようなものでしょうか。
※お好きな選択肢に〇をつけてください(手描きの〇付き)