Sign in Join
Wiki copytemporary

Flexible Array Member: what changed

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

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.
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.
22
3-## Introduction
3+## Contents
44
5-**Disclaimer:** *this section is pretty much a copy-paste from [Wikipedia article](https://en.wikipedia.org/wiki/Flexible_array_member)*
5+ * 1 Introduction
6+ * 2 Pascal
7+ * 2.1 Direct Addressing
8+ * 2.2 Using Additional Record
9+ * 2.3 Using Advanced Record
10+ * 3 See Also
611
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:
12+## Introduction
813
9-``` c
14+**Disclaimer:** _this section is pretty much a copy-paste from[Wikipedia article](<https://en.wikipedia.org/wiki/Flexible_array_member>)_
15+
16+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:
17+```
1018typedef struct mystruct
11-{
12- DWORD a;
13- DWORD b;
14- DWORD c[]; // the flexible array member must be last
15-};
19+ {
20+ DWORD a;
21+ DWORD b;
22+ DWORD c[]; // the flexible array member must be last
23+ };
1624```
1725
18-Typically, such structures serve as the header in a larger, variable memory allocation:
19-
20-``` c
26+Typically, such structures serve as the header in a larger, variable memory allocation:
27+```
2128struct mystruct* st= malloc(...);
22-...
23-for (int i = 0; i < st->b; i++)
24- st->c[i] = ...;
29+ ...
30+ for (int i = 0; i < st->b; i++)
31+ st->c[i] = ...;
2532```
2633
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.
34+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.
2835
29-It is common to allocate sizeof(struct) + array_len*sizeof(array element) bytes
36+It is common to allocate sizeof(struct) + array_len*sizeof(array element) bytes
3037
3138## Pascal
3239
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
40+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.
41+```
3642type
37- mystruct = record
38- a : DWORD;
39- b : DWORD;
40- end;
41- pmystruct = ^mystruct;
43+ mystruct = record
44+ a : DWORD;
45+ b : DWORD;
46+ end;
47+ pmystruct = ^mystruct;
4248```
4349
44-There are a few options on how the additional elements can be accessed:
50+There are a few options on how the additional elements can be accessed:
4551
4652### Direct Addressing
4753
48-By explicitly getting the address that goes after the header struct
49-
50-``` pascal
54+By explicitly getting the address that goes after the header struct
55+```
5156var
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] := ...;
57+ i : integer;
58+ buf : Pmystruct;
59+ c : PDword;
60+ begin
61+ GetMem(buf, sizeof(mystruct)+ extrasize);
62+ ...
63+ c:=Pointer(buf)+sizeof(mystruct);
64+
65+ for i := 0 to buf.b-1 do
66+ c[i] := ...;
6267```
6368
6469### Using Additional Record
6570
66-Depending on the use, the additional record could overlap with the original record using [[absolute]].
67-
68-``` pascal
71+Depending on the use, the additional record could overlap with the original record using [absolute](</index.php?title=absolute&action=edit&redlink=1> "absolute \(page does not exist\)").
72+```
6973type
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] := ...;
74+ mystructEx = record
75+ hdr : mystruct;
76+ c : PDword;
77+ end;
78+ pmystructEx = ^mystructEx;
79+
80+
81+ var
82+ i : integer;
83+ buf : PmystructEx;
84+ begin
85+ GetMem(buf, sizeof(mystruct)+ extrasize);
86+
87+ for i := 0 to buf.hdr.b-1 do
88+ buf.c[i] := ...;
8489```
8590
8691### Using Advanced Record
8792
88-Advanced records allow to methods and properties for records. Thus the field could be emulated through a method/property
89-
90-``` pascal
93+Advanced records allow to methods and properties for records. Thus the field could be emulated through a method/property
94+```
9195{$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;
96+
97+ type
98+ mystruct = packed record
99+ a,b: DWORD;
100+ function c: PDWORD; inline;
101+ end;
102+
103+ function mystruct.c: PDWORD;
104+ begin
105+ Result := PDWORD(pbyte(@self.b)+sizeOf(self.b));
106+ end;
103107```
104108
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
109+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)
110+```
108111{$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;
112+
113+ type
114+ mystruct = packed record
115+ a,b: DWORD;
116+ function c: PDWORD; inline;
117+ strict private
118+ cStart: record end;
119+ end;
120+
121+ function mystruct.c: PDWORD;
122+ begin
123+ Result := PDWORD(@cStart);
124+ end;
122125```
123126
124127## See Also
125128
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+ * <https://forum.lazarus.freepascal.org/index.php/topic,45998.0.html> \- original thread that started the discussion
130+ * <https://en.wikipedia.org/wiki/Flexible_array_member> \- wikipedia on Flexible Array Member
131+ * [[Common problems when converting C header files]]
129132
130133---
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).*
134+*From the Free Pascal wiki, page "Flexible Array Member", as the Internet Archive kept it on 2022-10-01. 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