unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;type
TRec=record
a: byte;
b: string;
c: integer;
d: string;
e: double;
f: string;
g: double;//TDateTime;
h: real;
i: byte;
j: byte;
end; TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
Button7: TButton;
Button8: TButton;
Button9: TButton;
Button10: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
procedure Button9Click(Sender: TObject);
procedure Button10Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;function GetSize(const s: string): Integer;var
Form1: TForm1;
r: TRec;
pr: ^TRec;
p: Pointer;implementation{$R *.DFM}function GetSize(const s: string): Integer;
var
SizePointer: Pointer;
begin
if Pointer(s)<>nil then
begin
SizePointer := Pointer(Integer(Pointer(s))-4);
result := Integer(SizePointer^);
end
else
result := 0;
end;procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
begin
r.a:=1;
r.b:='234567111111111111111111111';
//i:=sizeof(r.b);
r.c:=3;
r.d:='4';
r.e:=5.0;
r.f:='6';
r.g := now;
r.h :=8.0;
r.i :=9;
r.j :=10;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)); //a
(sender as Tbutton).caption := IntToStr(Integer(p^));
end;procedure TForm1.Button2Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)+4); //b ??+4
(sender as Tbutton).caption := String(p^);
end;procedure TForm1.Button3Click(Sender: TObject);
begin //c
p :=Pointer(Integer(@r)+8);
(sender as Tbutton).caption := IntToStr(Integer(p^));
end;procedure TForm1.Button4Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)+12); //d
(sender as Tbutton).caption := String(p^);
end;procedure TForm1.Button5Click(Sender: TObject);
begin //e
p :=Pointer(Integer(@r)+16);
(sender as Tbutton).caption := floattostr(double(p^));
end;procedure TForm1.Button6Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)+24); //f
(sender as Tbutton).caption := String(p^);
end;procedure TForm1.Button7Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)+32); //g
(sender as Tbutton).caption := DateTimeToStr(TDateTime(p^));
end;procedure TForm1.Button8Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)+40); //h
(sender as Tbutton).caption := floattostr(double(p^));//IntToStr(Integer(p^));
end;procedure TForm1.Button9Click(Sender: TObject);
var
a: ^byte;
begin //i
p :=Pointer(Integer(@r)+48);
(sender as Tbutton).caption := IntToStr(Integer(p^));
a := p;
(sender as Tbutton).caption := IntTostr(a^);
end;procedure TForm1.Button10Click(Sender: TObject);
begin //j
p :=Pointer(Integer(@r)+49); //??+1
(sender as Tbutton).caption := IntToStr(Byte(p^));
end;end.在访问r.f之前,我可以断定记录体中的每个域其实就是一个32位指针或者是64位指针。但是访问到后面的域时,这样的解释就好像不对了。希望大家可以给我一个合理的解释。
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;type
TRec=record
a: byte;
b: string;
c: integer;
d: string;
e: double;
f: string;
g: double;//TDateTime;
h: real;
i: byte;
j: byte;
end; TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
Button7: TButton;
Button8: TButton;
Button9: TButton;
Button10: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
procedure Button9Click(Sender: TObject);
procedure Button10Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;function GetSize(const s: string): Integer;var
Form1: TForm1;
r: TRec;
pr: ^TRec;
p: Pointer;implementation{$R *.DFM}function GetSize(const s: string): Integer;
var
SizePointer: Pointer;
begin
if Pointer(s)<>nil then
begin
SizePointer := Pointer(Integer(Pointer(s))-4);
result := Integer(SizePointer^);
end
else
result := 0;
end;procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
begin
r.a:=1;
r.b:='234567111111111111111111111';
//i:=sizeof(r.b);
r.c:=3;
r.d:='4';
r.e:=5.0;
r.f:='6';
r.g := now;
r.h :=8.0;
r.i :=9;
r.j :=10;
end;procedure TForm1.Button1Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)); //a
(sender as Tbutton).caption := IntToStr(Integer(p^));
end;procedure TForm1.Button2Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)+4); //b ??+4
(sender as Tbutton).caption := String(p^);
end;procedure TForm1.Button3Click(Sender: TObject);
begin //c
p :=Pointer(Integer(@r)+8);
(sender as Tbutton).caption := IntToStr(Integer(p^));
end;procedure TForm1.Button4Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)+12); //d
(sender as Tbutton).caption := String(p^);
end;procedure TForm1.Button5Click(Sender: TObject);
begin //e
p :=Pointer(Integer(@r)+16);
(sender as Tbutton).caption := floattostr(double(p^));
end;procedure TForm1.Button6Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)+24); //f
(sender as Tbutton).caption := String(p^);
end;procedure TForm1.Button7Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)+32); //g
(sender as Tbutton).caption := DateTimeToStr(TDateTime(p^));
end;procedure TForm1.Button8Click(Sender: TObject);
begin
p :=Pointer(Integer(@r)+40); //h
(sender as Tbutton).caption := floattostr(double(p^));//IntToStr(Integer(p^));
end;procedure TForm1.Button9Click(Sender: TObject);
var
a: ^byte;
begin //i
p :=Pointer(Integer(@r)+48);
(sender as Tbutton).caption := IntToStr(Integer(p^));
a := p;
(sender as Tbutton).caption := IntTostr(a^);
end;procedure TForm1.Button10Click(Sender: TObject);
begin //j
p :=Pointer(Integer(@r)+49); //??+1
(sender as Tbutton).caption := IntToStr(Byte(p^));
end;end.在访问r.f之前,我可以断定记录体中的每个域其实就是一个32位指针或者是64位指针。但是访问到后面的域时,这样的解释就好像不对了。希望大家可以给我一个合理的解释。
解决方案 »
- 请教delphi多线程技术监控多个串口
- 哪个高手用过JVCL组件,其中有一个消息提示控件(类似MSN 的消息提示框),叫什么名字?
- 将StringList转换成分号分隔的字符 和 反向的函数,请求优化,不怕代码难懂__这是新版本旧的有错误。
- bcb to delphi语法转换
- 使用tstringlist如何读取文本文件的最后三行值
- 一个关于DELPHI连接ACCESS的问题
- 怎么将ClientDataSet的一条纪录,向上或向下挪几条?
- 在pascal中,为什么针对文件操作的writeln,其内容要在屏幕中显示出来?
- 内存地址和指针的问题,pascal高手请回答
- 如何不区分大小写比较两个字符串?
- 请问后缀为.db的数据库是什么类型的?怎样创建它?在线!!~
- 急:怎样在Delphi中显示GIF动画?越简单越好!
比如:
procedure TForm1.Button1Click(Sender: TObject);
var
a: ^TRec;
begin
new(a);
a.a := 100;
a.b := 'abcd';
a.c := 300;
a.d := 'dddd';
a.e := 1000.230;
caption := string(pointer(integer(a)+12)^);
dispose(a);
end;这中间通过a的指针访问了域d. 其中指针加上了12是因为编译器在进行编译的时候要考虑字节对齐,所以a域虽然只占了一个字节但是还是分配了4个字节。
b域是字符串指针占4个字节,c域整数占4个字节。所以访问d域加上12即可。
编译器在编译的时候可以指定对齐的字节数.
设定方法: project --> option --> record field alignment 默认为8 .
如果该成1的话前面的偏移加9 即可。
就是编译器在进行编译的时候是怎样考虑字节对齐?有什么规律?
还有我贴出来的,你可以试下吗?
有时记录里面的域之间的偏移量是4,有时又是8,有时又是1.
其中我访问b域时,我只需在a域的地址上加4就可以,
但是我访问j域时,我却需在i域的地址上加1,访问的数据才正确,
如果是字节对齐的话,又怎么解释?
而且,我访问b,j域时,a,i类型时一致的,我认为象这种类型,
应该32位指针足够访问这种类型的数据了。
但是我在访问g域时,偏移量竟然不是4,而是8.我觉得这样很矛盾。因为前面我访问一个域(假设为1域时),那么它前面的一个0域同样是string类型,但是它们的偏移量是4.
但是这样字节对齐又明显不对,因为我如果有一个string类型的域,那它的偏移量也是4,不管它的长度有多长,当然在我贴出来的代码中,也试过这种类型的偏移量是8.现在也没办法解释它是如何通过4个字节去访问这个string类型的域。但是把它看成是一个域,这个现象就变得合情合理。可是有些情况又不能得到很好的解释。
不过,我觉得如果把域看成是一个指针,这样如果定义一个这种类型的数组,
我想它会省下很多存储空间的。
根据delphi的帮助说明:字节对齐的行为为了优化程序的运行速度。因为p2-p4的cpu的数据总线都是32位的(4byte),所以数据访问尽量按照4字节的倍数对齐。
我总结了几条编译器进行字节对齐的规律:
1. 在字节对齐的情况下delphi的所有纪录数据类型的占用字节数只能1,2,4,8等4中情况。其他情况如字符串和内存块用指针来表示,所有指针4个字节。
2. 编译器可以设定字节对齐的字节数,比如delphi默认的字节数是8个字节。这8个字节的意思是什么呢。好比一个写字板每行只能写8个字一样,就是说纪录的逻辑情形就是有多个8字节的行组成的,也就是一个( 8 x N )的一个矩形
而且规定一个域只可能在一行中,不能在两行中。3。那么compiler怎么在这一行行的8个字节中分配各个纪录域的呢?是这样的。前面说过了,数据域只可能1,2,4,8,如果不是的会加0补齐,而且数据与不能占两行.算法好像有点复杂,不过如果用笔在纸上画一下也就出来了,不过这理面还要4字节对齐的问题。比如三个域分别为(1,1,4)那么显然前两个1占用前两个字节,然后空两个字节,然后后面的4字节为第三域。说了一大堆不知道说明白没?
1。各种数据类型的大小;
byte(1); string指针(4); integer(4); double(8); real(6);
对齐时: real(8);|1234|5678|
|a000|--b-|
|-c--|--d-|
|----e----|
|-f--|0000| 因为g为8字节该行只剩余4字结了。
|----g----|
|--h----00|
|ij0000000|我对该纪录的各种变种作了测试均符合上面的规律。
不过我有一点要补充的,就是real类型的size跟double类型是一样大小的。
delphi的帮助是这么写的。
一开始这样认为主要是不清楚string实则是一个指针,
不过有一点也是不明白,delphi是怎么实现这样一个指针,
因为string类型不象c语言的pChar类型,还希望 findcsdn(findcsdn) 同志能再指教一下。