Aller au contenu

%SIZE

Taille en octets

Renvoie le nombre d'octets qu'une zone, un tableau ou une structure de données occupe en mémoire.

Syntaxe

%SIZE(zone)
%SIZE(tableau : *ALL)
zone
Une zone, un tableau, une structure de données, une sous-zone, ou une constante.
*ALL
Pour un tableau : la taille de tous les éléments, au lieu de celle d'un seul. Pour un tableau dim(*auto), c'est celle des éléments en cours.
Résultat
Un entier : la taille en octets. C'est une valeur fixe, qui ne dépend pas du contenu de la zone (voir le piège pour varchar).

À quoi ça sert

On s'en sert quand une API, un tampon ou un fichier veut une longueur en octets : la taille d'une structure de données à passer en paramètre, la place occupée par un tableau. Elle suit la déclaration : si on change une longueur, la valeur suit.

Exemple 1 : Tailles des types courants

**free
// %SIZE : nombre d'octets occupes en memoire par une zone.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s nom     char(12);
dcl-s montant packed(7:2);
dcl-s grand   packed(8:2);
dcl-s zone    zoned(7:2);
dcl-s petit   int(5);
dcl-s entier  int(10);
dcl-s jour    date;
dcl-s heure   time;
dcl-s horo    timestamp;

snd-msg 'char(12)       : ' + %char(%size(nom));
snd-msg 'packed(7:2)    : ' + %char(%size(montant));
snd-msg 'packed(8:2)    : ' + %char(%size(grand));
snd-msg 'zoned(7:2)     : ' + %char(%size(zone));
snd-msg 'int(5)         : ' + %char(%size(petit));
snd-msg 'int(10)        : ' + %char(%size(entier));
snd-msg 'date           : ' + %char(%size(jour));
snd-msg 'time           : ' + %char(%size(heure));
snd-msg 'timestamp      : ' + %char(%size(horo));

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

char(12)       : 12
packed(7:2)    : 4
packed(8:2)    : 5
zoned(7:2)     : 7
int(5)         : 2
int(10)        : 4
date           : 10
time           : 8
timestamp      : 26

Un char(12) occupe 12 octets, un zoned(7:2) 7. Un décimal condensé, lui, occupe moins que son nombre de chiffres : packed(7:2) fait 4 octets, packed(8:2) 5. Les entiers font 2 octets pour int(5) et 4 pour int(10), et une date, une heure et un horodatage 10, 8 et 26.

Exemple 2 : Zones variables, tableaux et structures

**free
// %SIZE : zones variables, tableaux et structures de donnees.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s libelle varchar(10);
dcl-s villes  char(12) dim(5);
dcl-s noms    varchar(20) dim(*auto : 7);
dcl-ds client qualified;
  numcli packed(5:0);
  nom    char(20);
  ville  char(12);
end-ds;

libelle = 'Lyon';
snd-msg 'varchar(10) : size ' + %char(%size(libelle)) + ', len ' + %char(%len(libelle));

// Tableau : un element, ou le tableau entier avec *ALL.
snd-msg 'villes      : un element ' + %char(%size(villes)) +
        ', total ' + %char(%size(villes : *all));

// dim(*auto) : *ALL suit le nombre d'elements en cours.
snd-msg 'noms vide   : total ' + %char(%size(noms : *all));
noms(*next) = 'Dupont SA';
noms(*next) = 'Leroy SARL';
snd-msg 'noms 2 elem : un element ' + %char(%size(noms)) +
        ', total ' + %char(%size(noms : *all));

// Structure de donnees : somme des sous-zones (3 + 20 + 12).
snd-msg 'client      : ' + %char(%size(client)) + ', dont nom ' + %char(%size(client.nom));

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

varchar(10) : size 12, len 4
villes      : un element 12, total 60
noms vide   : total 0
noms 2 elem : un element 22, total 44
client      : 35, dont nom 20

Un varchar(10) occupe 12 octets, qu'il contienne « Lyon » ou rien du tout, alors que %len donne 4. Pour un tableau, %size donne un élément (12) et %size(… : *all) l'ensemble (60). Avec dim(*auto), *all suit le contenu : 0 à vide, 44 avec deux éléments de 22 octets. Une structure de données fait la somme de ses sous-zones : 3 + 20 + 12 = 35.

Le piège

La taille n'est ni le nombre de chiffres ni la longueur du contenu. Un packed(7:2) fait 4 octets, pas 7. Un varchar(10) en fait 12 : 10 pour le contenu au maximum, plus 2 pour la longueur. %size renvoie 12 même quand la zone contient « Lyon » ; pour la longueur du contenu, on utilise %len.

Et sur un tableau, sans *all, on n'obtient que la taille d'un élément.