Difference between revisions of "Flexible Array Member/fr"

From Lazarus wiki
Jump to navigationJump to search
 
Line 29: Line 29:
  
 
==Pascal==
 
==Pascal==
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.
+
Pascal n'a pas de membre de tableau flexible, donc la structure doit être déclarée sans le membre supplémentaire, afin que sizeof(mystruct) renvoie la même valeur qu'en C.
 
<source lang="pascal">
 
<source lang="pascal">
 
type
 
type
Line 39: Line 39:
 
</source>
 
</source>
  
There are a few options on how the additional elements can be accessed:
+
Il existe quelques options pour accéder aux éléments supplémentaires :
  
 
===Adressage direct===
 
===Adressage direct===
By explicitly getting the address that goes after the header strucut
+
En obtenant explicitement l'adresse qui suit la structure d'en-tête
 
<source lang="pascal">
 
<source lang="pascal">
 
var
 
var
Line 57: Line 57:
 
</source>
 
</source>
  
===Using Additional Record===
+
===Utilisation d'enregistrement supplémentaire===
Depending on the use, the additional record could overlap with the original record using [[absolute]].
+
Selon l'utilisation, l'enregistrement supplémentaire pourrait chevaucher l'enregistrement d'origine en utilisant [[absolute/fr|absolute]].
 
<source lang="pascal">
 
<source lang="pascal">
 
type
 
type
Line 79: Line 79:
  
 
===Utilisation d'enegistrement avancé===
 
===Utilisation d'enegistrement avancé===
Advanced records allow to methods and properties for records. Thus the field could be emulated through a method/property
+
Les enregistrements avancés permettent d'utiliser des méthodes et des propriétés pour les enregistrements. Ainsi, le champ pourrait être émulé via une méthode/propriété
  
 
<source lang="pascal">
 
<source lang="pascal">
Line 96: Line 96:
 
</source>
 
</source>
  
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)
+
OU en utilisant un enregistrement vide. (Un enregistrement vide n'a pas de structure, mais permet d'obtenir une adresse, ce qui devrait faire gagner du temps sur le calcul de l'adresse)
  
 
<source lang="pascal">
 
<source lang="pascal">

Latest revision as of 12:48, 30 April 2022

English (en) français (fr)

C'est une caractéristique rarement utilisée en langage C. Elle a été introduite avec la norme C99. Elle n'a jamais été adoptée par le compilateur C++ (et cela pourrait être la raison de la rare utilisation). Quelques API à la C pourrait bénéficier de cette caractéristique, en particulier celles de bas niveau.

Introduction

Avertissement: cette section est à peu près un copier-coller de l'article Wikipedia

Le membre tableau flexible est un membre de struct, qui est un tableau sans dimension spécifiée. Il doit être le dernier membre d'un tel struct et doit être acompagné d'au moins un autre membre, comme dans l'exemple suivant:

typedef struct mystruct
{
  DWORD a;
  DWORD b;
  DWORD c[]; // le membre tableau flexible doit être le dernier
};

Généralement,de tels struct servent d'entête dans une plus large allocation mémoire variable:

struct mystruct* st= malloc(...);
...
for (int i = 0; i < st->b; i++)
     st->c[i] = ...;

L'operateur sizeof sur un tel struct donne la taille du struct comme si le membre tableau flexible était vide. Cela peut inclure un rembourrage ajouté pour accueillir l'élément flexible ; le compilateur est également libre de réutiliser ce remplissage dans le cadre du tableau lui-même.

Il est courant d'allouer sizeof(struct) + array_len*sizeof(array element) octets.

Pascal

Pascal n'a pas de membre de tableau flexible, donc la structure doit être déclarée sans le membre supplémentaire, afin que sizeof(mystruct) renvoie la même valeur qu'en C.

type
  mystruct = record
    a : DWORD;
    b : DWORD;
  end;
  pmystruct = ^mystruct;

Il existe quelques options pour accéder aux éléments supplémentaires :

Adressage direct

En obtenant explicitement l'adresse qui suit la structure d'en-tête

var
 i   : integer;
 buf : Pmystruct;
 c   : PDword;
begin
  GetMem(buf, sizeof(mystruct)+ extrasize);
  ...
  c:=Pointer(buf)+sizeof(mystruct);
  
  for i := 0 to buf.b-1 do
     c[i] := ...;

Utilisation d'enregistrement supplémentaire

Selon l'utilisation, l'enregistrement supplémentaire pourrait chevaucher l'enregistrement d'origine en utilisant absolute.

type
  mystructEx = record
    hdr : mystruct;
    c : PDword;
  end;
  pmystructEx = ^mystructEx;


var
 i   : integer;
 buf : PmystructEx;
begin
  GetMem(buf, sizeof(mystruct)+ extrasize);
  
  for i := 0 to buf.hdr.b-1 do
     buf.c[i] := ...;

Utilisation d'enegistrement avancé

Les enregistrements avancés permettent d'utiliser des méthodes et des propriétés pour les enregistrements. Ainsi, le champ pourrait être émulé via une méthode/propriété

{$modeswitch advancedrecords}

type
  mystruct = packed record
    a,b: DWORD;
    function c: PDWORD; inline;
  end;
 
function mystruct.c: PDWORD;
begin
  Result := PDWORD(pbyte(@self.b)+sizeOf(self.b));
end;

OU en utilisant un enregistrement vide. (Un enregistrement vide n'a pas de structure, mais permet d'obtenir une adresse, ce qui devrait faire gagner du temps sur le calcul de l'adresse)

{$modeswitch advancedrecords}

type
  mystruct = packed record
    a,b: DWORD;
    function c: PDWORD; inline;
  strict private
    cStart: record end;
  end;
 
function mystruct.c: PDWORD;
begin
  Result := PDWORD(@cStart);
end;

Voir aussi