Skip to content

FR: allow static arrays for that offsetof-like trick.

Previously on “Offsetof-like Trick”: #39665 (closed).

So far I didn’t need it personally (can’t be sure though, unless used as a constant it works and just results in worse code...), but studying the code involved in #39665 (closed) reveals that it still has no idea about arrays.

type
	PBContainer = ^BContainer;
	BContainer = record
		dummy: int32;
		b: int32;
	end;

	PMyObj = ^MyObj;
	MyObj = record
		dummy: int32;
		bs: array[0 .. 9] of BContainer;
	end;

const
	// FifthBOfs = PtrUint(@PMyObj(nil)^.bs[5].b); // does not compile
	FifthBOfs = PtrUint(@PMyObj(nil)^.bs) + 5 * sizeof(MyObj.bs[0]) + PtrUint(@PBContainer(nil)^.b); // ugly workaround

	function MyObjFromFifthB_SubOffsetOf(bPtr: PInt32): PMyObj;
	begin
		result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
		result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
		result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
		result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
		result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
		result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
		result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
		result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
		result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
		result := pointer(bPtr) - PtrUint(@PMyObj(nil)^.bs[5].b);
	end;

	procedure MyObjFromFifthB_SubOffsetOf_End; begin end;

	function MyObjFromFifthB_SubConst(bPtr: PInt32): PMyObj;
	begin
		result := pointer(bPtr) - FifthBOfs;
		result := pointer(bPtr) - FifthBOfs;
		result := pointer(bPtr) - FifthBOfs;
		result := pointer(bPtr) - FifthBOfs;
		result := pointer(bPtr) - FifthBOfs;
		result := pointer(bPtr) - FifthBOfs;
		result := pointer(bPtr) - FifthBOfs;
		result := pointer(bPtr) - FifthBOfs;
		result := pointer(bPtr) - FifthBOfs;
		result := pointer(bPtr) - FifthBOfs;
	end;

	procedure MyObjFromFifthB_SubConst_End; begin end;

var
	mo: MyObj;
begin
	writeln('''bs[5].b'' offset in ''MyObj'': ', FifthBOfs);
	writeln('@mo: ', HexStr(@mo));

	writeln('@mo recovered from @mo.bs[5].b by subtracting "offsetof": ', HexStr(MyObjFromFifthB_SubOffsetOf(@mo.bs[5].b)));
	writeln('@mo recovered from @mo.bs[5].b by subtracting constant:   ', HexStr(MyObjFromFifthB_SubConst(@mo.bs[5].b)));

	writeln('Code size for ten subtractions of "offsetof": ', CodePointer(@MyObjFromFifthB_SubOffsetOf_End) - CodePointer(@MyObjFromFifthB_SubOffsetOf));
	writeln('Code size for ten subtractions of constant: ', CodePointer(@MyObjFromFifthB_SubConst_End) - CodePointer(@MyObjFromFifthB_SubConst));

	if MyObjFromFifthB_SubOffsetOf(@mo.bs[5].b) <> @mo then
		halt(1);

	if MyObjFromFifthB_SubConst(@mo.bs[5].b) <> @mo then
		halt(2);

	if CodePointer(@MyObjFromFifthB_SubOffsetOf_End) - CodePointer(@MyObjFromFifthB_SubOffsetOf)
		<> CodePointer(@MyObjFromFifthB_SubConst_End) - CodePointer(@MyObjFromFifthB_SubConst)
	then
		halt(3);
end.
'bs[5].b' offset in 'MyObj': 24
@mo: 0000000100012010
@mo recovered from @mo.bs[5].b by subtracting "offsetof": 0000000100012010
@mo recovered from @mo.bs[5].b by subtracting constant:   0000000100012010
Code size for ten subtractions of "offsetof": 112
Code size for ten subtractions of constant: 48
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information