场景: 假如我们要调用A函数 procedure A( aBytes:Tbytes).
你手上现在只有一个STRING, 或者其他数组类型,比如Array of char. array of integer..一般的过程就是,首先把你手上的数组类型转换成符合A调用的需要的类型TBYTES,,其实很多时候我们需要要这个TBYTES纯粹是为了得到一个A函数运行的结果,BYTES其实并没有什么用,只是一个中间数据。但是有没有想过,转换的过程其实需要内存开销的,内存要分配,数据要复制,最后销毁。能不能把不同类型的数组共享在一块内存上。比如STRING,既可以当TBYTES用,也可以当 比如ARRAY OF INTEGER. 答案是肯定的。
玩法基础分析:一个动态数组的三要素,内存首地址,长度,元素大小。
内存首地址:简单,内存地址是可以相互贴的(贴就是指针共同指向一个地方)。直接赋值就行。
var Abytes:Tbytes; aIntegers: array of integer;
贴: Abytes:=Pointer(aIntegers);
元素大小:简单, SIZEOF(BYTE),sizeof(ineteger);
剩下就是长度在哪里?
长度:
DELPHI的动态数组管理有头部。位置就在动态数组指针的前面。头部有什么。。每个版本都不一样。但是一样的是,动态数组的前4个字节就是动态数组的长度(包括字符串也是如此)。
这样就可以愉快的玩耍了。
下面列文给出了一个字符串S变成TBYTES S的例子,但是A和S共享一块内存。 也就是说只有的类型转换没有涉及到内存的新的分配。
function NewtypeFunction(const A: tbytes): string;
begin
System.SetLength(Result, System.Length(A) shr 1);
System.Move(A[0], result[1], Length(A));
end;
procedure TForm1.btn1Click(Sender: TObject);
var
A: TBytes;
S: string;
begin
// A 和S共享一个内存地址。达到类型转换。
S := ‘我的agbc’;
A := Pointer(@S[1]); // 直接指针贴上去 ,共同指向一块内存
PInteger(PByte(A) – 4)^ := Length(S) shl 1; //脱离D对TBYTES的管理,修正TBYTES的长度
ShowMessage(NewtypeFunction(A)); // TBYTES活了。 能用。
PInteger(PByte(A) – 4)^ := Length(A) shr 1; // 恢复 S字符串长度。
A := nil;// 插去屁股
end;
特别献给老程序员,过去D7都是用PANSICHAR的干活,现在D库很多函数需要TBYTES的干活。。代码升级。。吃一壶
经常碰到这样的场景。
宁波空。(Q:9534557)