Forum > General

[SOLVED] Different size of Record for different order of fields

(1/2) > >>

Okoba:
Can anyone tell me how this happens, for example showing how the calculation works? I knew there is byte align, but why it changes this way?

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program Project1; type  R1 = record    C1: Char;    I1: Integer;    C2: Char;    I2: Integer;  end;   R2 = record    C1: Char;    C2: Char;    I1: Integer;    I2: Integer;  end;   R3 = record    I1: Integer;    C1: Char;    I2: Integer;    C2: Char;  end;   R4 = record    I1: Integer;    I2: Integer;    C1: Char;    C2: Char;  end;begin  WriteLn(SizeOf(R1), ' ', SizeOf(R2), ' ', SizeOf(R3), ' ', SizeOf(R4)); //16 12 16 12  ReadLn;end.                              

TRon:

--- Quote from: Okoba on February 18, 2024, 06:47:59 am ---Can anyone tell me how this happens, for example showing how the calculation works? I knew there is byte align, but why it changes this way?

--- End quote ---
There is such a beautiful manual that was painstakingly written by its authors with years and years of labour that explains all these kind of things :)

Use the packed keyword like f.e.:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  R1 = packed record    C1: Char;    I1: Integer;    C2: Char;    I2: Integer;  end; for all your record definitions to get them al the same size. There are other directives that can manipulate the memory layout of the fields in a record such as align, packrecords and codealign.

It is about preferable layout in memory (and that is platform specific).

edit

--- Quote ---//16 12 16 12

--- End quote ---

As to proof the point that it is platform specific for me the output reads:

--- Code: ---8 6 8 6

--- End code ---

Okoba:
@TRon I read the documentation beforehand. I liked to know more on how it calculates this, I am just curious about the " platform specific" part. For example on Windows 64bit, and with FPC 64bit, how it aligns the record like that?

TRon:

--- Quote from: Okoba on February 18, 2024, 10:15:38 am ---I am just curious about the " platform specific" part. For example on Windows 64bit, and with FPC 64bit, how it aligns the record like that?

--- End quote ---
I can't tell.... because:

..as written in the documentation there is a whole list of rules for that (record layout and size) and besides the platform ABI rules it also depends in what mode you compile (size of integer can change for instance) and what your settings are for codealign (for default values for your specific win64 target see file  "/compiler/system/i_win.pas" in the compiler sources and look there for a variable named "system_x64_win64_info", and the field named "alignment")

And there is ofc. the align/packrecords directive that is able to influence the layout of a record (I haven't figured out yet where the default value for packrecords is set). Even when you do not set any of these options they do have default values (which the compiler works with to determine the in-memory layout).

fwiw, I never rely on any of the default rules/options being applied by the compiler except for two, the first is "packrecords c" in case I have to work with c-related structures and the latter is to always use a packed record

Perhaps a more knowledgeable person is able to shed a better/brighter light on the subject for you ?

PS: The following code based on yours, is at least able to show what actually happens:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program program1; type  PR1 = ^TR1;  TR1 = record    C1: Char;    I1: Integer;    C2: Char;    I2: Integer;  end;   PR2 = ^TR2;  TR2 = record    C1: Char;    C2: Char;    I1: Integer;    I2: Integer;  end;   PR3 = ^TR3;  TR3 = record    I1: Integer;    C1: Char;    I2: Integer;    C2: Char;  end;   PR4 = ^TR4;  TR4 = record    I1: Integer;    I2: Integer;    C1: Char;    C2: Char;  end; procedure dump;const  HT =#9;begin  writeln('offset', HT, 'size', HT, 'name');  writeln(PtrUInt(@PR1(nil)^.C1), HT, SizeOf(TR1.C1), HT, 'TR1.C1');  writeln(PtrUInt(@PR1(nil)^.I1), HT, SizeOf(TR1.I1), HT, 'TR1.I1');  writeln(PtrUInt(@PR1(nil)^.C2), HT, SizeOf(TR1.C2), HT, 'TR1.C2');  writeln(PtrUInt(@PR1(nil)^.I2), HT, SizeOf(TR1.I2), HT, 'TR1.I2');  writeln('SizeOf(TR1) = ', SizeOf(TR1));  writeln;  writeln('offset', HT, 'size', HT, 'name');  writeln(PtrUInt(@PR2(nil)^.C1), HT, SizeOf(TR2.C1), HT, 'TR2.C1');  writeln(PtrUInt(@PR2(nil)^.C2), HT, SizeOf(TR2.C2), HT, 'TR2.C2');  writeln(PtrUInt(@PR2(nil)^.I1), HT, SizeOf(TR2.I1), HT, 'TR2.I1');  writeln(PtrUInt(@PR2(nil)^.I2), HT, SizeOf(TR2.I2), HT, 'TR2.I2');  writeln('SizeOfT(R2) = ', SizeOf(TR2));  writeln;  writeln('offset', HT, 'size', HT, 'name');  writeln(PtrUInt(@PR3(nil)^.I1), HT, SizeOf(TR3.I1), HT, 'TR3.I1');  writeln(PtrUInt(@PR3(nil)^.C1), HT, SizeOf(TR3.C1), HT, 'TR3.C1');  writeln(PtrUInt(@PR3(nil)^.I2), HT, SizeOf(TR3.I2), HT, 'TR3.I2');  writeln(PtrUInt(@PR3(nil)^.C2), HT, SizeOf(TR3.C2), HT, 'TR3.C2');  writeln('SizeOf(R3) = ', SizeOf(TR3));  writeln;  writeln('offset', HT, 'size', HT, 'name');  writeln(PtrUInt(@PR4(nil)^.I1), HT, SizeOf(TR4.I1), HT, 'TR4.I1');  writeln(PtrUInt(@PR4(nil)^.I2), HT, SizeOf(TR4.I2), HT, 'TR4.I2');  writeln(PtrUInt(@PR4(nil)^.C1), HT, SizeOf(TR4.C1), HT, 'TR4.C1');  writeln(PtrUInt(@PR4(nil)^.C2), HT, SizeOf(TR4.C2), HT, 'TR4.C2');  writeln('SizeOf(R4) = ', SizeOf(TR4));  writeln;end; begin  dump;end. 
Which for me is:

--- Code: ---offset size name
0 1 TR1.C1
2 2 TR1.I1
4 1 TR1.C2
6 2 TR1.I2
SizeOf(TR1) = 8

offset size name
0 1 TR2.C1
1 1 TR2.C2
2 2 TR2.I1
4 2 TR2.I2
SizeOfT(R2) = 6

offset size name
0 2 TR3.I1
2 1 TR3.C1
4 2 TR3.I2
6 1 TR3.C2
SizeOf(R3) = 8

offset size name
0 2 TR4.I1
2 2 TR4.I2
4 1 TR4.C1
5 1 TR4.C2
SizeOf(R4) = 6

--- End code ---

PascalDragon:

--- Quote from: Okoba on February 18, 2024, 10:15:38 am ---For example on Windows 64bit, and with FPC 64bit, how it aligns the record like that?

--- End quote ---

As a really rough estimate: fields will be aligned on their natural alignment which usually is equivalent to their size. To 1-Byte types will have a 1-Byte alignment, 2-Byte types will have a 2-Byte alignment and so on. There are exceptions, but in general one can work with this rule. Thus you should be able to figure out the differences for the records in your original post.

Navigation

[0] Message Index

[#] Next page

Go to full version