Sign in Join
Wiki copytemporary

Flexible Array Member: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Flexible Array Member

OldNewLine
1+Is a rarely used feature of C language. It was introduced with C99 standard. The feature was never adopted by C++ compiler (and that might be the reason of the rate use). Some C-like APIs could benefit from the feature, especially low level ones.
2+
3+## Introduction
4+
5+**Disclaimer:** *this section is pretty much a copy-paste from [Wikipedia article](https://en.wikipedia.org/wiki/Flexible_array_member)*
6+
7+Flexible Array Member is a member of a struct, which is an array without a given dimension. It must be the last member of such a struct and it must be accompanied by at least one other member, as in the following example:
8+
9+``` c
10+typedef struct mystruct
11+{
12+ DWORD a;
13+ DWORD b;
14+ DWORD c[]; // the flexible array member must be last
15+};
16+```
17+
18+Typically, such structures serve as the header in a larger, variable memory allocation:
19+
20+``` c
21+struct mystruct* st= malloc(...);
22+...
23+for (int i = 0; i < st->b; i++)
24+ st->c[i] = ...;
25+```
26+
27+The sizeof operator on such a struct gives the size of the structure as if the flexible array member was empty. This may include padding added to accommodate the flexible member; the compiler is also free to re-use such padding as part of the array itself.
28+
29+It is common to allocate sizeof(struct) + array_len*sizeof(array element) bytes
30+
31+## Pascal
32+
33+Pascal doesn't have flexible array member, thus the structure should be declared without the additional member, in order for sizeof(mystruct) to return the same value as in C.
34+
35+``` pascal
36+type
37+ mystruct = record
38+ a : DWORD;
39+ b : DWORD;
40+ end;
41+ pmystruct = ^mystruct;
42+```
43+
44+There are a few options on how the additional elements can be accessed:
45+
46+### Direct Addressing
47+
48+By explicitly getting the address that goes after the header struct
49+
50+``` pascal
51+var
52+ i : integer;
53+ buf : Pmystruct;
54+ c : PDword;
55+begin
56+ GetMem(buf, sizeof(mystruct)+ extrasize);
57+ ...
58+ c:=Pointer(buf)+sizeof(mystruct);
59+
60+ for i := 0 to buf.b-1 do
61+ c[i] := ...;
62+```
63+
64+### Using Additional Record
65+
66+Depending on the use, the additional record could overlap with the original record using [[absolute]].
67+
68+``` pascal
69+type
70+ mystructEx = record
71+ hdr : mystruct;
72+ c : PDword;
73+ end;
74+ pmystructEx = ^mystructEx;
75+
76+var
77+ i : integer;
78+ buf : PmystructEx;
79+begin
80+ GetMem(buf, sizeof(mystruct)+ extrasize);
81+
82+ for i := 0 to buf.hdr.b-1 do
83+ buf.c[i] := ...;
84+```
85+
86+### Using Advanced Record
87+
88+Advanced records allow to methods and properties for records. Thus the field could be emulated through a method/property
89+
90+``` pascal
91+{$modeswitch advancedrecords}
92+
93+type
94+ mystruct = packed record
95+ a,b: DWORD;
96+ function c: PDWORD; inline;
97+ end;
98+
99+function mystruct.c: PDWORD;
100+begin
101+ Result := PDWORD(pbyte(@self.b)+sizeOf(self.b));
102+end;
103+```
104+
105+OR using an empty record. (An empty record has not struct, yet allows to get an address, which should save some time on address calculation)
106+
107+``` pascal
108+{$modeswitch advancedrecords}
109+
110+type
111+ mystruct = packed record
112+ a,b: DWORD;
113+ function c: PDWORD; inline;
114+ strict private
115+ cStart: record end;
116+ end;
117+
118+function mystruct.c: PDWORD;
119+begin
120+ Result := PDWORD(@cStart);
121+end;
122+```
123+
124+## See Also
125+
126+- <https://forum.lazarus.freepascal.org/index.php/topic,45998.0.html> - original thread that started the discussion
127+- <https://en.wikipedia.org/wiki/Flexible_array_member> - wikipedia on Flexible Array Member
128+- [[Common problems when converting C header files]]
129+
130+---
131+*From the Free Pascal wiki, page "Flexible Array Member", as it stood on 2022-04-30 after a change by E-ric, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history