Sign in Join
Wiki copytemporary

Flexible Array Member: what changed

Revision 2 to 3. 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.
2-
3-## Contents
4-
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
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.
112
123## Introduction
134
14-**Disclaimer:** _this section is pretty much a copy-paste from[Wikipedia article](<https://en.wikipedia.org/wiki/Flexible_array_member>)_
5+**Disclaimer:** *this section is pretty much a copy-paste from [Wikipedia article](https://en.wikipedia.org/wiki/Flexible_array_member)*
156
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-```
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
1810typedef struct mystruct
19- {
20- DWORD a;
21- DWORD b;
22- DWORD c[]; // the flexible array member must be last
23- };
11+{
12+ DWORD a;
13+ DWORD b;
14+ DWORD c[]; // the flexible array member must be last
15+};
2416```
2517
26-Typically, such structures serve as the header in a larger, variable memory allocation:
27-```
18+Typically, such structures serve as the header in a larger, variable memory allocation:
19+
20+``` c
2821struct mystruct* st= malloc(...);
29- ...
30- for (int i = 0; i < st->b; i++)
31- st->c[i] = ...;
22+...
23+for (int i = 0; i < st->b; i++)
24+ st->c[i] = ...;
3225```
3326
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.
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.
3528
36-It is common to allocate sizeof(struct) + array_len*sizeof(array element) bytes
29+It is common to allocate sizeof(struct) + array_len*sizeof(array element) bytes
3730
3831## Pascal
3932
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-```
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
4236type
43- mystruct = record
44- a : DWORD;
45- b : DWORD;
46- end;
47- pmystruct = ^mystruct;
37+ mystruct = record
38+ a : DWORD;
39+ b : DWORD;
40+ end;
41+ pmystruct = ^mystruct;
4842```
4943
50-There are a few options on how the additional elements can be accessed:
44+There are a few options on how the additional elements can be accessed:
5145
5246### Direct Addressing
5347
54-By explicitly getting the address that goes after the header struct
55-```
48+By explicitly getting the address that goes after the header struct
49+
50+``` pascal
5651var
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] := ...;
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] := ...;
6762```
6863
6964### Using Additional Record
7065
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-```
66+Depending on the use, the additional record could overlap with the original record using [[absolute]].
67+
68+``` pascal
7369type
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] := ...;
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] := ...;
8984```
9085
9186### Using Advanced Record
9287
93-Advanced records allow to methods and properties for records. Thus the field could be emulated through a method/property
94-```
88+Advanced records allow to methods and properties for records. Thus the field could be emulated through a method/property
89+
90+``` pascal
9591{$modeswitch advancedrecords}
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;
107-```
10892
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)
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;
110103```
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
111108{$modeswitch advancedrecords}
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;
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;
125122```
126123
127124## See Also
128125
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]]
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]]
132129
133130---
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).*
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