IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

Commande Sizeof "imprécise"


Sujet :

Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 9
    Par défaut Commande Sizeof "imprécise"
    Bonjour,

    Une âme charitable pourrait m'expliquer pourquoi lorsque je tape ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Label1: TLabel;
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.DFM}
     
    procedure TForm1.Button1Click(Sender: TObject);
     
    type everec=record
            cpt:byte;
            code:string[2];
            comm:string[13];
         end;
    begin
     label1.caption:=inttostr(sizeof(everec));
     
    end;
     
    end.
    La valeur renvoyé est elle de 24 ?
    Un à un chaque élément cpt, code et comm vaut 4 , 3 et 14. Mais quand je les mets tous comme ici, j'obtiens 24 au lieu de 21. Si je ne laisse que les string j'obtiens bien 17 (ok). Seulement le longint 4 (ok). Mais les deux string et le longint 24 !! Quelque chose m'échappe...

    Merci,
    Thierry

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 086
    Par défaut
    Tu confonds
    - SizeOf (Taille Mémoire)
    - Length (Taille logique des chaines ou tableau)

    ensuite

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    everec=record
            cpt:byte;
            code:string[2];
            comm:string[13];
    end;
    Cpt = 1 (byte = 1 par de integer en vue ?)
    code = 3
    comm = 14
    total = 18

    Ensuite, pour une raison de compilateur, les champs sont espacés en mémoire pour les caler des les registres 32 ou 64 bits, donc avec Cpt en Word, cela peut changer, ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    everec=record
            cpt:integer;
            code:string[2];
            comm:string[13];
    end;
    Cpt = 4
    code = 3
    comm = 14
    bourrage = 3 // je ne sais pas pk mais il y est !
    total = 24

    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    everec= packed record // packed !!! 
            cpt:integer;
            code:string[2];
            comm:string[13];
    end;
    Cpt = 4
    code = 3
    comm = 14
    total = 21
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre éclairé
    Profil pro
    Développeur Java
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Par défaut
    bourrage = 3 -> je pense qu'il s'agit de l'optimisation pour les Intel 486. En effet pour améliorer les performances, il faut les mettres sur des adresses mémoires paires.
    En plus, il ne faut pas oublier que les strings ne sont pas gérées comme des simples tableaux de caractères (voir C. Quelques précisions sur le type string http://reisubar.developpez.com/tutor...trings-pchars/)

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 086
    Par défaut
    Oui, le bourrage c'est de l'alignement de champ pour les registres processeurs, mais je n'ai pas trouvé d'autre nom ...

    sinon, les chaines courtes (string[xx]) ce ne sont que de simple tableau avec un byte en [0] pour indiquer la véritable, longueur, à ne pas confondre avec les chaines longues AnsiString (ou string) qui sont en fait un pointeur sur une zone mémoire contenant la chaine, précédé par structure contenant la longueur etr le compteur de référence ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    everec=packed record
            cpt:byte;
            code:string;
            comm:string;
    end;
    Cpt = 4
    code = 4 // pointeur seulement
    comm = 4
    total = 12
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Expert confirmé

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Par défaut
    En fait la structure de string est plutôt comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    type
      TStringRec = packed record
        RefCounter: Cardinal;
        Length: Cardinal;
        Contents: array[0..Length] of Char;
      end;
    Bien sûr le "tableau" Contents a une taille qui dépend de la longueur de la chaîne. Le "pointeur" chaîne pointe vers @Contents, et pas vers @RefCounter ! Pour une chaîne vide, ce pointeur vaut nil, au lieu de pointer sur une structure avec 0 comme Length.

    Et oui, Contents va bien de 0 à Length, car il y a toujours un #0 en bout de chaîne, qui permet le transtypage direct en PChar.
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 086
    Par défaut
    Il y a deux #0 pour les WideString ... ^_^, d'ailleurs, j'ai écrit cette fonction pour réduire une chaine, très rapidement (le code est illisible à cause de variante possible d'écriture)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    {* -----------------------------------------------------------------------------
    la fonction ReduceStr correspond à un SetLength plus performant mais peut-être plus risqué !
    @param S est une variable chaîne
    @param NewLength indique le nouveau nombre de caractères dans S.
    ------------------------------------------------------------------------------ }
    procedure ReduceStr(var S: string; NewLength: Integer);
    {$IFNDEF PUREPASCAL}
    type
      PStrRec = ^StrRec;
      StrRec = packed record
        refCnt: Longint;
        length: Longint;
      end;
     
    const
      skew = sizeof(StrRec);
      rOff = sizeof(StrRec); { refCnt offset }
      overHead = sizeof(StrRec) + 1;
     
    {$IFDEF SHAI_REALLOC_STRING}
    var
      P: PStrRec;
    {$ENDIF}
    {$ENDIF}
    begin
      if NewLength < 0 then
        NewLength := 0;
      if NewLength < Length(S) then
      begin
          {$IFDEF PUREPASCAL}
          SetLength(S, NewLength);
          {$ELSE}
          {$IFDEF SHAI_REALLOC_STRING}
          P := Pointer(Integer(S) - SizeOf(StrRec));
          ReallocMem(P, NewLength + skew); // Revient à faire le SetLength en terme de temps
          {$ELSE}
          S[Succ(NewLength)] := #0;
          {$ENDIF}
          {$IFDEF SHAI_SET_LENGTH}
          Integer(Pointer(Integer(@S[1])-4)^) := NewLength; // FreeMem libère le pointeur, peut importe la taille
          {$ELSE}
          PStrRec(Integer(S) - SizeOf(StrRec)).length := NewLength;
          {$ENDIF}
          {$ENDIF}
       end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo