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

Lazarus Pascal Discussion :

Données différentes entre array statique et array dynamique [Lazarus]


Sujet :

Lazarus Pascal

  1. #21
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 130
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 130
    Par défaut
    Bonsoir,


    Citation Envoyé par bb84000 Voir le message
    Au moins si on était obligé d'écrire MyDynArray[i]^ pour accéder à un élément sans que le compilo râle, on ne risquerait pas d'oublier que c'est un pointeur.

    Au fait peut-on écrire SizeOf(MyDynArray[i]^) pour avoir la taille de l'élément ?
    Merci pour cette idée de page anglophone, elle est effectivement plus copieuse.

    Mais pour répondre à ta question (et à mes interrogations), je n'ai vu nulle part la notation MyDynArray[i]^, et si je la tente le compilo crie très fort "illegal je sais plus quoi".

    Quant à ton SizeOf, je te renvoie à la page wiki anglophone :
    Citation Envoyé par wiki
    Remember, sizeOf of a dynamic array evaluates to the size of a pointer.

  2. #22
    Membre très actif
    Homme Profil pro
    libre
    Inscrit en
    Juin 2019
    Messages
    205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : libre

    Informations forums :
    Inscription : Juin 2019
    Messages : 205
    Par défaut
    Tu es en train de nous dire que les tableaux dynamiques ont un comportement... aléatoire ?
    Dans l'exemple j'ai évoqué la raison: l'appelle de SetLength .. c'est après d'un redimensionnement que ça se reproduit pourtant les deux variables pouvaient modifier le même tableau:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    B := A;
    B[2]:=1500;
    ShowmessageFmt('%d',[A[2]]);// Affiche 1500

    Au fait peut-on écrire SizeOf(MyDynArray[i]^) pour avoir la taille de l'élément ?
    C'est pas possible a moins dans le cas d'un tableau de pointeurs array of PInteger... mais aujourd'hui les pointeurs et les tableaux dynamiques font deux pas de liens apparents entre les deux par exemple si tu conserves une adresse d'un élément @tab[2] pour une utilisation ultérieure tu n'aurais aucune garantie qu'elle reste valide après un redimensionnement par contre l’accès par l'indice est toujours garantie.

  3. #23
    Membre chevronné

    Homme Profil pro
    Retraité
    Inscrit en
    Avril 2012
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2012
    Messages : 181
    Par défaut
    Bonjour,

    Citation Envoyé par Jipété Voir le message
    Mais pour répondre à ta question (et à mes interrogations), je n'ai vu nulle part la notation MyDynArray[i]^, et si je la tente le compilo crie très fort "illegal je sais plus quoi".

    Quant à ton SizeOf, je te renvoie à la page wiki anglophone :
    Dommage. Et je me suis trompé pour SizeOf(MyDynArray[^]),on devrait avoir non la taille du pointeur, puisqu'on le déréférence, ni celle de l'élément (c'est length), mais celle de son type. Mais puisque tu dis que le compilo ne veut pas qu'on déréférence soi même un dynamic array...

    bb84000

  4. #24
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 130
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 130
    Par défaut
    Salut,

    Citation Envoyé par wheel Voir le message
    Dans l'exemple j'ai évoqué la raison : l'appel de SetLength...
    Non, tu n'en parlais pas, il n'y avait que le code, que je n'ai pas compris tout de suite pour la bonne et simple raison que l'aide de Lazarus ne s'applique pas à la construction de ton instruction Insert...

    Alors j'ai fait avec des ShowMessage et un Tmemo pour voir les données :
    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
    var
      A, B: array of integer;
      i: integer;
    begin
      showmessage(inttostr(Length(A))); // 0
      Insert([1, 2, 3, 4, 5], A, MAXINT);// ajouter des valeurs dans le tableau A
      showmessage(inttostr(Length(A))); // 5
      B := A; // les données du tableau A sont recopiées dans le tableau B...
     
      SetLength(A,Length(A)); // à quoi sert cette ligne ? à dissocier les deux tableaux ?
      showmessage(inttostr(Length(A))); // 5
     
      showmessage(inttostr(Length(B))); // 5, ... qui est dimensionné par la copie
     
      // pour vérifier les tableaux :
      for i := low(A) to high(A) do 
        memo.Lines.Add(inttostr(i)+' '+inttostr(A[i])+' '+inttostr(B[i]));
     
      // lors de l'erreur, penser à cliquer sur "continuer" pour voir le memo
      if A <> B then
         raise Exception.Create('A et B n''utilisent pas le même tableau');
      // les dimensions et les données étant identiques, l'erreur montre donc
      // qu'il y a d'autres paramètres pris en compte pour la comparaison :
      // les adresses des tableaux, forcément différentes ?
     
      SetLength(A,0); // libérations 
      SetLength(B,0);
    end;
     
    // le mémo :
    0 1 1
    1 2 2
    2 3 3
    3 4 4
    4 5 5
    Et effectivement, selon la présence ou l'absence de cette ligne SetLength, toutes choses égales par ailleurs, on a l'erreur ou pas.
    Bien sûr, on le voit mieux en rajoutant une ligne, genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      SetLength(A,Length(A)); // à quoi sert cette ligne ? à dissocier les deux tableaux ?
      showmessage(inttostr(Length(A))); // 5
      B[2] := 99; // ajout
    car là, le log ne loupe pas la différence :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    0 1 1
    1 2 2
    2 3 99
    3 4 4
    4 5 5
    Bon, c'est plus clair, le tout sera de s'en souvenir !


    Citation Envoyé par wheel Voir le message
    ... mais aujourd'hui les pointeurs et les tableaux dynamiques font deux pas de liens apparents entre les deux par exemple si tu conserves une adresse d'un élément @tab[2] pour une utilisation ultérieure tu n'aurais aucune garantie qu'elle reste valide après un redimensionnement par contre l’accès par l'indice est toujours garanti.
    Ensuite, ci-dessus, je trouve que ça manque de ponctuation et donc de précision : ce bout peut se lire de deux manières (j'ai eu le cas tout récemment avec un code en C : avec ce PasEnDegres, je ne sais pas si tu parles d'un écart (StepsInDegrees) ou d'une information (NotInDegrees)), la manière brouillonne, limite illisible et où il faut s'y prendre à plusieurs fois :
    les pointeurs et les tableaux dynamiques font deux pas de liens apparents entre les deux par exemple si tu conserves une adresse d'un élément @tab[2] pour une utilisation ultérieure tu n'aurais aucune ...

    Ce "deux pas de liens" m'a perturbé je te raconte pas !
    L'autre manière :

    les pointeurs et les tableaux dynamiques font deux : il n'y a pas de lien apparent entre les deux.
    Par exemple, si tu conserves une adresse d'un élément (addr := @tab[2]) pour une utilisation ultérieure, tu n'auras aucune...


    Allez, c'est tout pour le moment, c'est dimanche, il fait beau, il ne nous tombe pas encore de bombes sur la tête, tout va bien (ici).

  5. #25
    Membre très actif
    Homme Profil pro
    libre
    Inscrit en
    Juin 2019
    Messages
    205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : libre

    Informations forums :
    Inscription : Juin 2019
    Messages : 205
    Par défaut
    il n'y avait que le code, que je n'ai pas compris tout de suite pour la bonne et simple raison que l'aide de Lazarus ne s'applique pas à la construction de ton instruction Insert...
    Insert est comme celle utilisée pour les string est pour insérer un ou plusieurs éléments ou un autre tableau dans une position précise, MAXINT demande l'insertion a la fin du tab s'il n'est pas vide...on peut simplifier le code A := [1, 2, 3, 4, 5];

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    B := A; // les données du tableau A sont recopiées dans le tableau B...
    C''est vrai pour les tab statiques pour les dynamiques la taille d'un variable est fixe et éguale toujours celle d'un pointeur SizeOf(A)=SizeOf(Pointer)
    le variable ne contient que l'adresse du premier élément du tableau et donc l'affectation B := A ne concerne que cette valeur (adresse) qui sera recopiée à B et après ca le programme incrémente le compteur de références du tableau(voir le premier champ sur la photo) pour indiquer qu'il est encours d'utilisation et le maintenir en mémoire... pour déréférencer ou dissocier un variable du tableau B := nil le programme va décrémenter cette fois le compteur de références si ce compteur atteint 0 le tableau sera libéré automatiquement de la mémoire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      SetLength(A,0); // libérations 
      SetLength(B,0);
    Pas besoin ...les variables de type T D sont dissociés automatiquement a la fin de la fonction ...tu peux imaginer ce code invisible
    dans le cas d'un seul tab utilisés par A et B:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    A := nil;//  le compteur de références décrémenté ( 2 -> 1)
    B := nil; // le compteur de références décrémenté ( 1 -> 0) un zéro le tab sera libérer ici
    end;
    dans le cas ou chaque variable a son propre tab :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    A := nil;//  le compteur de références décrémenté ( 1 -> 0)un zéro le tab A libérer ici
    B := nil; // le compteur de références décrémenté ( 1 -> 0) un zéro le tab B libérer ici
    end;
    Ainsi a la sortie de la fonction tous les tableaux crées localement seront libérés s'ils n'ont pas été assignés a des des variables extérieures.

    B := A


    Une petite différence entre Delphi et Pasccal concernant le champ length:
    Delphi y enregistre le nombre d'éléments (Length)
    Pascal y enregistre l'indice la plus haute (Length-1)

    tu peux voir l' exemple de AndNotOr

    https://www.developpez.net/forums/d2.../#post11911029

  6. #26
    Membre chevronné

    Homme Profil pro
    Retraité
    Inscrit en
    Avril 2012
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2012
    Messages : 181
    Par défaut
    Bonjour,

    Un bout de code qui ne sert à rien, pour créer son propre array dynamique, juste pour s'amuser :

    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
    Type
      TWordArray = Array [0..0] of Word;
      PWordArray = ^TWordArray;
     
    procedure SetLength(var PWArr: PWordArray; len: Integer); // J'ajoute une nouvelle option de SetLength
    begin
      GetMem(PWArr, len*SizeOf(Word));
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      MyPWarray: PWordArray;
    begin
      SetLength(MyPWarray, 10);
      MyPWarray^[5]:= 14;
      ShowMessage(InttoStr(MyPWarray^[5]));
    end;
    Le compilo prévient qu'on est en dehors des clous puisqu'au départ, on a un tableau statique de 1 élément, mais il laisse faire.
    Ça marche même si on dépasse la longueur, il y a surement une explication

  7. #27
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 130
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 130
    Par défaut
    Coucou,

    tiens, ça va me changer du C,
    Citation Envoyé par bb84000 Voir le message
    Un bout de code qui ne sert à rien, pour créer son propre array dynamique, juste pour s'amuser :
    Tout sert toujours à quelque chose,

    Le même en vachement plus simple et plus lisible, surtout (les hiéroglyphes à coups de chapeau chinois ça me...)
    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
    procedure TForm1.Button1Click(Sender: TObject); // 4test
    Type
    //  TWordArray = Array [0..0] of Word;
      TWordArray = Array of Word;
    //inutile  PWordArray = ^TWordArray;
    var
    //  MyPWarray: PWordArray;
      MyWordArray: TWordArray;
    begin
    {  SetLength(MyPWarray, 10);
      MyPWarray^[5]:= 14;
      ShowMessage(InttoStr(MyPWarray^[5]));}
      SetLength(MyWordArray, 10);
      MyWordArray[15]:= 42; // :-)
      ShowMessage(InttoStr(MyWordArray[15]));
    end;
    Citation Envoyé par bb84000 Voir le message
    Le compilo prévient qu'on est en dehors des clous puisqu'au départ, on a un tableau statique de 1 élément, mais il laisse faire.
    Ça marche même si on dépasse la longueur, il y a surement une explication
    À moi il ne me dit rien, à part la non initialisation du tableau.

    Et, oui, le dépassement du tableau ça surprend, mais il me semble l'avoir lu qqpart...
    Nom : 42.png
Affichages : 380
Taille : 6,8 Ko

    (ça avance, ça avance...)

  8. #28
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 491
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Coucou,

    tiens, ça va me changer du C,

    Tout sert toujours à quelque chose,

    Le même en vachement plus simple et plus lisible, surtout (les hiéroglyphes à coups de chapeau chinois ça me...)
    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
    procedure TForm1.Button1Click(Sender: TObject); // 4test
    Type
    //  TWordArray = Array [0..0] of Word;
      TWordArray = Array of Word;
    //inutile  PWordArray = ^TWordArray;
    var
    //  MyPWarray: PWordArray;
      MyWordArray: TWordArray;
    begin
    {  SetLength(MyPWarray, 10);
      MyPWarray^[5]:= 14;
      ShowMessage(InttoStr(MyPWarray^[5]));}
      SetLength(MyWordArray, 10);
      MyWordArray[15]:= 42; // :-)
      ShowMessage(InttoStr(MyWordArray[15]));
    end;

    À moi il ne me dit rien, à part la non initialisation du tableau.

    Et, oui, le dépassement du tableau ça surprend, mais il me semble l'avoir lu qqpart...
    Nom : 42.png
Affichages : 380
Taille : 6,8 Ko

    (ça avance, ça avance...)
    salut

    regarde dans tes paramettre ... le debordement de pile doit etre decoché
    en delphi il y a cette option cocher "Verifier les limites"
    je suppose qu'en pascal il doit y avoir la meme chose

  9. #29
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 130
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 130
    Par défaut
    Citation Envoyé par anapurna Voir le message
    regarde dans tes paramètres ... le debordement de pile doit être décoché
    en delphi il y a cette option cocher "Verifier les limites"
    je suppose qu'en pascal il doit y avoir la meme chose
    C'est de cette option dont tu parles ?
    Nom : options.png
Affichages : 266
Taille : 8,9 Ko

    ou celle en haut à droite (2e colonne) ?
    Bah, dans les deux cas il ne me dit rien.

  10. #30
    Membre chevronné

    Homme Profil pro
    Retraité
    Inscrit en
    Avril 2012
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2012
    Messages : 181
    Par défaut
    Bonjour,

    Jipété, j'ai bien écrit que cela ne servait à rien. Bien entendu qu'on peut utiliser l'array dynamique de FPC, mais ce n'est pas le but de mon exemple qui est plutôt de faire joujou avec les pointeurs.

    Donc je crée le type et une nouvelle option de paramètre pour SetLength en dehors des procédures de la forme (en fait je pourrais très bien le créer dans une unité distincte). Et quand le curseur de la souris passe sur SetLength, on a alors un nouveau choix, en plus des deux existants (String et Array).

    bb84000

  11. #31
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 130
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 130
    Par défaut
    Citation Envoyé par anapurna Voir le message
    regarde dans tes paramètres ... le débordement de pile doit être décoché
    En fait, c'est dans le code qu'il faut insérer cette ligne :
    {$rangeChecks on}

    et du coup,
    Nom : rangecheckerror.png
Affichages : 260
Taille : 25,4 Ko

  12. #32
    Membre émérite
    Homme Profil pro
    Chef de projets retraité
    Inscrit en
    Juillet 2011
    Messages
    452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Chef de projets retraité
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2011
    Messages : 452
    Par défaut
    Bonjour

    En fait, c'est dans le code qu'il faut insérer cette ligne :
    {$rangeChecks on}
    C'est aussi l'option Intervalle (-Cr)
    dans les options du projet...

    Cordialement

  13. #33
    Membre chevronné

    Homme Profil pro
    Retraité
    Inscrit en
    Avril 2012
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2012
    Messages : 181
    Par défaut
    Bonsoir !

    On oublie les chapeaux chinois de Jipété et les erreurs d'intervalle :

    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
    Type
      PArray = ^Word;     // Similaire à un array de Word
     
    procedure SetLength(var PWArr: PArray; len: Integer);
    begin
      GetMem(PWArr, len*SizeOf(PWArr[0]));        // On alloue la mémoire nécessaire
      FillByte(PWArr^, len*SizeOf(PWArr[0]), 0);   // et on remplit  tout ça de 0
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      MyPWarray: PArray;
      i: Integer;
    begin
        SetLength(MyPWarray, 10);
        MyPWarray[8]:= 42;
        ShowMessage(InttoStr(MyPWarray[8]));
    end;
    Bon j'arrête pour ce soir !

    bb84000

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 1
    Dernier message: 26/04/2012, 14h05
  2. Réponses: 15
    Dernier message: 20/03/2008, 09h33
  3. tri des données différent entre 2 bases
    Par j6m dans le forum Oracle
    Réponses: 2
    Dernier message: 12/03/2006, 10h17
  4. [cr 8.5] comment exploiter les données d'un "array"
    Par kikidrome dans le forum SAP Crystal Reports
    Réponses: 12
    Dernier message: 09/06/2005, 14h03
  5. passage en paramètre d'un array dynamique 2D
    Par Guigui_ dans le forum Langage
    Réponses: 4
    Dernier message: 27/11/2002, 19h47

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