(10-08-2017, Saat: 16:06)uparlayan Adlı Kullanıcıdan Alıntı: SizeOf bazı veri tiplerinde doğru sonucu vermez bilginize...
Neden ?
Çünkü;
SizeOf, bir değişkenin veya type'in bayt cinsinden depolama boyutunu verir.
Length ise bir dizinin veya stringin karakter sayısını verir.
Aradaki farkı aşağıdaki örnek kod parçacığından da test edebilirsiniz;
procedure TForm1.Button1Click(Sender: TObject);
var
S: String;
begin
S := 'ali veli';
Memo1.Clear;
memo1.Lines.Add(SizeOf(S).ToString); // 4
memo1.Lines.Add(Length(S).ToString); // 8
end;
Bu konunun uzmanı değilim, böyle bir sorunun sorulmuş olmasını da açıkçası olumlu buluyorum, zira bu tarz kaliteli sorular çoğaldıkça insanın feyz alması başka bir keyif veriyor.
Ben olaya biraz daha farklı bakıp, variant değişkenin bir dizi olması durumunda bunun TByte cinsinden nasıl toplanabileceği ile ilgili farklı bir örnek kod paylaşmak istiyorum, (dediğim gibi fazla bir bilgim yok, o nedenle beni fazla hırpalamayın lütfen
)
( Aşağıdaki kodu spagetti bulabilirsiniz, bazı veri tipleri için tam olarak bitmediğini de ifade etmek lazım, mazur görün lütfen. )
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Data.DB, Datasnap.DBClient,
SynEdit, SynMemo;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TSynMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TByteArr = TBytes; // veya aşağıdaki gibi
//TByteArr = array of Byte;
var
Form1: TForm1;
implementation
{$R *.dfm}
function StrToByte(const Value: String): TByteArr;
var
I : Integer;
Ebat: Integer;
begin
Ebat := Length(Value);
SetLength(Result, Ebat);
for I := 0 to Ebat - 1 do Result[I] := ord(Value[I + 1]);
end;
function ByteToByte(const Value: Byte): TByteArr;
begin
SetLength(Result, 1);
Result[0] := TByteArr(@Value)[ 0 ];
end;
function IntToByte(const Value: Integer): TByteArr;
var
I : Integer;
begin
SetLength(Result, 4);
for I := 0 to 3 do Result[I] := TByteArr(@Value)[ I ];
end;
function WordToByte(const Value: Word): TByteArr;
begin
SetLength(Result, 2);
Result[0] := TByteArr (@Value) [ 0 ];
Result[1] := TByteArr (@Value) [ 1 ];
end;
function LongWordToByte(const Value: LongWord): TByteArr;
var
I : Integer;
begin
SetLength(Result, 4);
for I := 0 to 3 do Result[I] := TByteArr(@Value)[I];
end;
function Int64ToByte(const Value: Int64): TByteArr;
var
I : Integer;
Ebat: Integer;
begin
Ebat := SizeOf(Value);
SetLength(Result, Ebat);
for I := 0 to Ebat - 1 do Result[I] := TByteArr(@Value)[I];
end;
function VarToByte(const Value: Variant; var BaytSayisi: Integer): TByteArr;
var
Ebat, EkEbat: Integer;
Miktar : Integer;
Pointer : PVariant;
I, J, Q, W : Integer;
VeriTipi : Integer;
Eklenti : TByteArr;
W64 : Int64;
Wrd : Word;
LW : LongWord;
S: String;
begin
if (VarIsArray(Value) = TRUE) then begin
// Diziyi kilitleyip, gerçek değerleri tutan belleğe işaretçi koyuyoruz, bu anlamda aslında bu tıpkı SQL'de CURSOR kullanmaya benziyor...
Pointer := VarArrayLock(Value);
// Dizinin ilk bakıştaki uzunluğunu elde ediyoruz, bazı veri tipleri veriy yerine adresi tuttuğu için bu böyle...
Ebat := VarArrayHighBound(Value, 1) - VarArrayLowBound(Value, 1) + 1;
// Sonuç kümesinin boyunu parametremizdekiyle eşitliyoruz, ki zaten devamında bu kısım genişleyecek ama şimdilik bu böyle...
SetLength(Result, Ebat);
J := 0; // Sonuç kümesindeki bayt sayısını bununla takip edeceğiz...
Miktar := Ebat; // Bu aslında varyant dizinin eleman sayısını veriyor...
for I := 0 to Miktar - 1 do begin // Variant Dizinin her bir elemanı üzerinde tek tek tarama yapıyoruz...
VeriTipi := VarType(Pointer^);
case VeriTipi of
varBoolean : begin
Result[J] := Pointer^;
Inc(J);
end;
varByte : begin
Result[J] := Pointer^;
Inc(J);
end;
varSmallInt ,
varWord : begin
Wrd := Pointer^;
EkEbat := SizeOf(Wrd); // Buna da Dikkat !
SetLength(Eklenti, EkEbat);
Eklenti := WordToByte(Wrd);
Ebat := Ebat + EkEbat - 1;
SetLength(Result, Ebat);
for Q := 0 to EkEbat - 1 do begin
Result[J] := Eklenti[Q];
Inc(J);
end;
end;
varLongWord : begin
Wrd := Pointer^;
EkEbat := SizeOf(Wrd); // Buna da Dikkat !
SetLength(Eklenti, EkEbat);
Eklenti := LongWordToByte(Wrd);
Ebat := Ebat + EkEbat - 1;
SetLength(Result, Ebat);
for Q := 0 to EkEbat - 1 do begin
Result[J] := Eklenti[Q];
Inc(J);
end;
end;
varSingle ,
varDouble ,
varCurrency : begin
// araştırma konusu...
end;
varOleStr ,
// varStrArg ,
// varObject ,
varUStrArg ,
// varAny ,
varUString ,
varString : begin
S := Pointer^;
EkEbat := Length(S); // Dikkat !
SetLength(Eklenti, EkEbat);
Eklenti := StrToByte(S);
Ebat := Ebat + EkEbat - 1;
SetLength(Result, Ebat);
for Q := 0 to EkEbat - 1 do begin
Result[J] := Eklenti[Q];
Inc(J);
end;
end;
varInteger : begin
W := Pointer^;
EkEbat := SizeOf(W); // Buna da Dikkat !
SetLength(Eklenti, EkEbat);
Eklenti := IntToByte(W);
Ebat := Ebat + EkEbat - 1;
SetLength(Result, Ebat);
for Q := 0 to EkEbat - 1 do begin
Result[J] := Eklenti[Q];
Inc(J);
end;
end;
varInt64 : begin
W64 := Pointer^;
EkEbat := SizeOf(W64); // Buna da Dikkat !
SetLength(Eklenti, EkEbat);
Eklenti := Int64ToByte(W64);
Ebat := Ebat + EkEbat - 1;
SetLength(Result, Ebat);
for Q := 0 to EkEbat - 1 do begin
Result[J] := Eklenti[Q];
Inc(J);
end;
end;
end;
Inc(Pointer); // Sonraki elemanına geçiyoruz
end;
VarArrayUnlock(Value); // Dizinin kilidini açıyoruz...
BaytSayisi := J;
end else begin
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ba: TByteArr;
I: Integer;
V: Variant;
vava: array of Variant;
X: Integer;
function iif(aBoolean: Boolean; aTrue: string; aFalse: String): String;
begin
if aBoolean then Result := aTrue else Result := aFalse;
end;
begin
Memo1.Lines.Clear;
V := Variant('abuzer kadayıf');
vava := [ Byte(3)
, V
, Integer(1453)
, SmallInt(1453)
, Int64(1071)
, word(65537) // 256x256=65536 !
, AnsiString('AAA')
, String('BBB')
, WideString('CCC')
];
ba := VarToByte(Vava, X);
for I := Low(ba) to High(ba) do begin
Memo1.Lines.Add( IntToHex( ba[I], 4)
+ ' '
+ iif(ba[I] > 31, Chr(ba[I]), ' ' )
+ ' (' + ba[I].ToString + ')'
);
end;
Memo1.Lines.Add('Bayt Sayısı = ' + X.ToString);
SetLength(ba, 0);
//FreeAndNil(ba);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
S: String;
begin
S := 'ali veli';
Memo1.Clear;
memo1.Lines.Add(SizeOf(S).ToString); // = 4
memo1.Lines.Add(Length(S).ToString); // = 8
end;
end.