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

 C Discussion :

Idées de fonctions standards pour manipuler les pointeurs


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut Idées de fonctions standards pour manipuler les pointeurs
    Bonjour,

    Je cherche à faire une refonte de ma bibliothèque de fonctions en tenant compte de mes erreurs passées.
    J'en profite pour essayer d'y intégrer de nouvelles fonctions de manipulation des pointeurs dites standards/usuelles.

    Ces fonctions seront appliquées à tous les types, de short à unsigned long long int.
    Ensuite, elles seront "réencapsulées" dans une structure qui gérera implicitement la taille des tableaux 1D.
    Ensuite idem pour les tableaux 2D puis 3D.

    Et en parallèle, l'écriture d'une documentation sous doxygen.

    Par conséquent, voici le header pour les pointeurs d'entiers de type int en 1D sans gestion implicite des tailles.
    Je pense que les noms de fonctions sont explicites, si ce n'est pas le cas, je préciserai.
    L'esprit est que si vous avez d'autres fonctions du genre à proposer, je suis preneur.

    En vous remerciant par avance.

    ptr.h
    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
     
    #ifndef PTR_H
    #define PTR_H
     
    #define TRUE 1
    #define FALSE 0
     
    typedef long long int t_int64;
    typedef unsigned long long int t_uint64;
    typedef unsigned short t_boolean;
     
    void      i_1D_deallocate      ( int *p );
    int      *i_1D_allocate        ( t_uint64 p_sz );
    t_boolean i_1D_realloc         ( int **p, t_uint64 *p_sz, t_uint64 new_sz );
    t_boolean i_1D_insert          ( int **p, t_uint64 *p_sz, t_uint64 offset, int v );
    int      *i_1D_extract         ( int *p, t_uint64 p_sz, t_uint64 i0, t_uint64 i1, t_uint64 *q_sz );
    t_boolean i_1D_split           ( int *p, t_uint64 *p_sz, int **p1, t_uint64 *p1_sz, int **p2, t_uint64 *p2_sz, t_uint64 offset );
    t_boolean i_1D_remove          ( int **p, t_uint64 *p_sz, t_uint64 offset );
    int      *i_1D_copy            ( int *p, t_uint64 p_sz );
    t_boolean i_1D_replace         ( int *p0, t_uint64 p0_sz, int *p1, t_uint64 p1_sz );
    t_boolean i_1D_init            ( int *p, t_uint64 p_sz, t_uint64 v );
    int      *i_1D_rshift          ( int *p, t_uint64 p_sz, t_uint64 shift );
    int      *i_1D_lshift          ( int *p, t_uint64 p_sz, t_uint64 shift );
    t_boolean i_1D_rshift_self     ( int *p, t_uint64 p_sz, t_uint64 shift );
    t_boolean i_1D_lshift_self     ( int *p, t_uint64 p_sz, t_uint64 shift );
    void      i_1D_replace_partial ( int *p0 , int *p1, t_int64 i_for_start, t_uint64 i_for_end, t_uint64 i_p0, t_int64 i_p1, short p0_sign, short p1_sign );
     
    #endif
    Juste pour info bien que non pertinent ici.

    ptr.c
    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
     
    #include <stdio.h>
    #include <stdlib.h>
    #include "ptr.h"
     
    void i_1D_deallocate( int *p )
    {
        if ( p ) { free( p ), p = NULL; }
    }
     
    int *i_1D_allocate( t_uint64 p_sz )
    {
        int *p = NULL;
        if ( ( p = (int*)malloc( p_sz*sizeof(int) ) ) )
        {
            t_uint64 i;
            for ( i=0 ; i<p_sz ; i++ )
                p[i] = 0;
        }
        return p;
    }
     
    t_boolean i_1D_realloc( int **p, t_uint64 *p_sz, t_uint64 new_sz )
    {
        t_boolean b = FALSE;
        if ( *p && new_sz != 0 )
        {
            int *p_realloc = NULL;
            if ( ( p_realloc = (int*)realloc( (*p), new_sz*sizeof(int) ) ) )
            {
                (*p) = p_realloc;
                t_uint64 i;
                for ( i=*p_sz ; i<new_sz ; i++ )
                    (*p)[i] = 0;
     
                *p_sz = new_sz;
                b = TRUE;
            }
        }
        return b;
    }
     
    t_boolean i_1D_insert( int **p, t_uint64 *p_sz, t_uint64 offset, int v )
    {
        t_boolean b = FALSE;
        if ( *p && 0 <= offset && offset < *p_sz+1 )
        {
            if ( i_1D_realloc( p, p_sz, *p_sz+1 ) == TRUE )
            {
                t_uint64 i;
                 for ( i=(*p_sz)-1 ; i>offset ; i-- )
                    (*p)[i] = (*p)[i-1];
     
                (*p)[offset] = v;
                b = TRUE;
            }
        }
        return b;
    }
     
    int *i_1D_extract( int *p, t_uint64 p_sz, t_uint64 i0, t_uint64 i1, t_uint64 *q_sz )
    {
        int *q = NULL;
        if ( p && p_sz >= i1-i0 )
        {
            *q_sz = i1-i0+1;
            if ( ( q = i_1D_allocate(*q_sz) ) )
                i_1D_replace_partial( q, p, i0, i1+1, i0, 0, 1, 1 );
        }
        return q;
    }
     
    t_boolean i_1D_split( int *p, t_uint64 *p_sz, int **p1, t_uint64 *p1_sz, int **p2, t_uint64 *p2_sz, t_uint64 offset )
    {
        t_boolean b = FALSE;
        if ( p && 0 <= offset && offset < *p_sz )
        {
            if ( ((*p1) = i_1D_extract( p, *p_sz, 0, offset, p1_sz )) && ((*p2) = i_1D_extract( p, *p_sz, offset+1, *p_sz-1, p2_sz )) )
                b = TRUE;
     
        }
        return b;
    }
     
    int *i_1D_copy( int *p, t_uint64 p_sz )
    {
        int *q = NULL;
        if ( p && p_sz != 0 )
        {
            if ( ( q = i_1D_allocate(p_sz) ) )
                i_1D_replace_partial( q, p, 0, p_sz, 0, 0, 1, 1);
        }
        return q;
    }
     
    t_boolean i_1D_remove( int **p, t_uint64 *p_sz, t_uint64 offset )
    {
        t_boolean b = FALSE;
        if ( *p && 0 <= offset && offset < *p_sz )
        {
            t_uint64 q_sz = *p_sz; t_uint64 index = 0;
            int *q = i_1D_copy( (*p), *p_sz );
            if ( i_1D_realloc( p, p_sz, *p_sz-1 ) == TRUE )
            {
                t_uint64 i;
                for ( i=0 ; i<q_sz ; i++ )
                {
                    if ( i != offset )
                        (*p)[index] = q[i], index++;
                }
                i_1D_deallocate( q );
                b = TRUE;
            }
        }
        return b;
    }
     
    t_boolean i_1D_replace( int *p0, t_uint64 p0_sz, int *p1, t_uint64 p1_sz )
    {
        t_boolean b = FALSE;
        if ( p0 && p1 && p0_sz >= p1_sz )
        {
            i_1D_replace_partial( p0, p1, 0, p1_sz, 0, 0, 1, 1);
            b = TRUE;
        }
        return b;
    }
     
    t_boolean i_1D_init( int *p, t_uint64 p_sz, t_uint64 v )
    {
        t_boolean b = FALSE;
        if ( *p && p_sz > 0 )
        {
            t_uint64 i = 0;
            for ( i=0 ; i<p_sz ; i++ )
                p[i] = v;
     
            b = TRUE;
        }
        return b;
    }
     
    void i_1D_replace_partial( int *p0 , int *p1, t_int64 i_for_start, t_uint64 i_for_end, t_uint64 i_p0, t_int64 i_p1, short p0_sign, short p1_sign )
    {
        t_int64 i = 0;
        for ( i=i_for_start ; i<i_for_end ; i++ )
            p0[i+p0_sign*i_p0] = p1[i+p1_sign*i_p1];
    }
     
    int *i_1D_rshift( int *p, t_uint64 p_sz, t_uint64 shift )
    {
        int *q = NULL;
        if ( p && p_sz>0 && shift>= 0 )
        {
            shift %= p_sz;
            if ( shift != 0 )
            {
                int *r = NULL;
                if ( ( r = i_1D_allocate(p_sz + shift) ) )
                {
                    i_1D_replace_partial( r, p, 0, p_sz, shift, 0, 1, 1);
                    if ( ( q = i_1D_allocate( p_sz ) ) )
                    {
                        i_1D_replace_partial( q, r, p_sz, p_sz+shift, p_sz, 0, -1, 1);
                        i_1D_replace_partial( q, r, shift, p_sz, 0, 0, 1, 1);
                    }
                    i_1D_deallocate( r );
                }
            }
            else
            {
                if ( !( q = i_1D_copy( p, p_sz ) ) );
            }
        }
        return q;
    }
     
    int *i_1D_lshift( int *p, t_uint64 p_sz, t_uint64 shift )
    {
        int *q = NULL;
        if ( p && p_sz>0 && shift>= 0 )
        {
            shift %= p_sz;
            if ( !( q = i_1D_rshift(p, p_sz, p_sz-shift) ) );
        }
        return q;
    }
     
    t_boolean i_1D_rshift_self( int *p, t_uint64 p_sz, t_uint64 shift )
    {
        t_boolean b = FALSE;
        int *q = NULL;
        if ( ( q = i_1D_rshift( p, p_sz, shift ) ) )
        {
            i_1D_replace_partial( p, q, 0, p_sz, 0, 0, 1, 1 );
            i_1D_deallocate( q );
            b = TRUE;
        }
        return b;
    }
     
    t_boolean i_1D_lshift_self( int *p, t_uint64 p_sz, t_uint64 shift )
    {
        t_boolean b = FALSE;
        int *q = NULL;
        if ( ( q = i_1D_lshift( p, p_sz, shift ) ) )
        {
            i_1D_replace_partial( p, q, 0, p_sz, 0, 0, 1, 1 );
            i_1D_deallocate( q );
            b = TRUE;
        }
        return b;
    }

  2. #2
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Bonjour,

    en première lecture je dirai qu'à moins d'être certain de ne pas avoir les types (u)intN_t avec N=8,16,32,64 il ne faut pas émettre l'hypothèse qu'un long long fait 64 bits de large, et là à nouveau tu peux le tester avec un sizeof et CHAR_BIT → utiliser stdint et inttype est un atout.
    À l'instar de la remarque précédente tu peux aussi utiliser le type _Bool pour les booléens → stdbool.
    Utilise le type size_t pour spécifier des tailles d'objets, c'est le type qu'attendent les fonctions comme malloc, realloc, …

    Autant utiliser les types proposés par le langage avant de faire des typedef qui pourraient être dangereux.

    Dans i_1D_allocate le ,p=NULL est totalement inutile.
    Ne caste pas les mallocs.
    Les remplissage ne me paraît pas nécessaire à l'allocation ou la réallocation.

  3. #3
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 510
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 510
    Par défaut
    Bonjour,

    Comme l'a dit picodev, il vaut mieux utiliser des types standards.

    Cela implique de remplacer :
    • t_boolean, TRUE et FALSE par bool, true et false définis dans <stdbool.h> (C99)
    • t_uint64 par size_t
    • t_int64 par ptrdiff_t défini dans <stddef.h>


    Citation Envoyé par darkwall_37 Voir le message
    Ces fonctions seront appliquées à tous les types, de short à unsigned long long int.
    Dans ce cas, pour factoriser le code, je conseille l'utilisation de macros.
    Exemple :
    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
    #define DEFINITION_1D_allocate(type) \
    type* type##_1D_allocate( size_t p_sz ) \
    { \
        type *p = NULL; \
        if ( ( p = (type*)malloc( p_sz*sizeof(type) ) ) ) \
        { \
            size_t i; \
            for ( i=0 ; i<p_sz ; i++ ) \
                p[i] = 0; \
        } \
        return p; \
    }
     
    typedef unsigned uint;
    DEFINITION_1D_allocate(uint) // définit la fonction "uint* uint_1D_allocate(size_t)"
    EDIT :
    Citation Envoyé par picodev Voir le message
    Ne caste pas les mallocs.
    Pourquoi ?

  4. #4
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Citation Envoyé par picodev Voir le message
    Ne caste pas les mallocs.
    Citation Envoyé par Pyramidev Voir le message
    EDIT :
    Pourquoi ?
    Faut-il caster malloc ?

    Je rajoute que cela surcharge la lecture, tout comme le rappel du type dans le sizeof. Je trouve que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    t_nom_du_type *new=(t_nom_du_type *) malloc( nombre * sizeof(t_nom_du_type) )
    est bien plus lourd et moins clair, plus difficile à refactorer, qu'un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    t_nom_du_type *new=malloc( nombre * sizeof *new );
    Il y a aussi les cas «limites», si on oublie de prototyper malloc en oubliant d'inclure stdlib alors le compilateur supposera qu'il renvoie un int. Ce qui n'est pas franchement grave mais pas franche propre en 32 bits, mais pire en 64 bits.

  5. #5
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Citation Envoyé par Pyramidev Voir le message
    Bonjour,

    Comme l'a dit picodev, il vaut mieux utiliser des types standards.

    Cela implique de remplacer :
    • t_boolean, TRUE et FALSE par bool, true et false définis dans <stdbool.h> (C99)
    • t_uint64 par size_t
    • t_int64 par ptrdiff_t défini dans <stddef.h>



    Dans ce cas, pour factoriser le code, je conseille l'utilisation de macros.
    Exemple :
    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
    #define DEFINITION_1D_allocate(type) \
    type* type##_1D_allocate( size_t p_sz ) \
    { \
        type *p = NULL; \
        if ( ( p = (type*)malloc( p_sz*sizeof(type) ) ) ) \
        { \
            size_t i; \
            for ( i=0 ; i<p_sz ; i++ ) \
                p[i] = 0; \
        } \
        return p; \
    }
     
    typedef unsigned uint;
    DEFINITION_1D_allocate(uint) // définit la fonction "uint* uint_1D_allocate(size_t)"
    EDIT :

    Pourquoi ?
    Salut pyramidev, merci pour ta réponse.
    Je ne connaissais pas la factorisation avec les macros. Intéressant.
    Est ce que la présence des \ est normal ?

    Est-ce que tu voulais dire ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    typedef unsigned int uint;
    DEFINITION_1D_allocate(uint) // définit la fonction "uint* uint_1D_allocate(size_t)"
    à la place de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typedef unsigned uint;
    DEFINITION_1D_allocate(uint) // définit la fonction "uint* uint_1D_allocate(size_t)"
    Ou c'est moi qui comprend pas ?

  6. #6
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Salut picodev,

    Super, merci pour tes précisions =)
    size_t c'est 4 octets ( Windows 10 x64 ) donc ça veut dire qu'avec un malloc actuellement on ne peut pas allouer plus de 4Go de mémoire sur ce type de système ?

    Pourquoi dans i_1D_allocate, p=NULL est inutile? Enfin l'est-ce vraiment ? Ça mange pas de pain quoi, et ça m'arrache les yeux d'écrire int *p;
    Je suis bien conscient que malloc renvoit NULL ou non NULL donc effectivement, en soit ce n'est pas indispensable d'initialiser à NULL avec le malloc derrière.
    D'un point de vue fonctionnel, ce n'est pas nécessaire mais plus pour la logique de dire j'initialise chaque variable même si je le test suivant induit que se sera NULL ou non NULL.

    Après idem pour l'initialisation des valeurs dans le tableau. Pour moi, ça permet de repérer plus vite les erreurs. J'imagine que pour de l'optimisation, c'est pas top en effet, ça fait du taff en plus pour rien quand on sait bien ce qu'on fait derrière et qu'on part du principe qu'on ne fait jamais d'erreur. Moi c'est pas mon cas xD

  7. #7
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Citation Envoyé par darkwall_37 Voir le message
    Salut picodev,

    Super, merci pour tes précisions =)
    size_t c'est 4 octets ( Windows 10 x64 ) donc ça veut dire qu'avec un malloc actuellement on ne peut pas allouer plus de 4Go de mémoire sur ce type de système ?
    size_t, même sur windows, n'a pas la même taille entre le 64 et 32 bits. * cf edit en fin de post.

    Citation Envoyé par darkwall_37 Voir le message
    Pourquoi dans i_1D_allocate, p=NULL est inutile? Enfin l'est-ce vraiment ? Ça mange pas de pain quoi, et ça m'arrache les yeux d'écrire int *p;
    Je suis bien conscient que malloc renvoit NULL ou non NULL donc effectivement, en soit ce n'est pas indispensable d'initialiser à NULL avec le malloc derrière.
    D'un point de vue fonctionnel, ce n'est pas nécessaire mais plus pour la logique de dire j'initialise chaque variable même si je le test suivant induit que se sera NULL ou non NULL.

    Après idem pour l'initialisation des valeurs dans le tableau. Pour moi, ça permet de repérer plus vite les erreurs. J'imagine que pour de l'optimisation, c'est pas top en effet, ça fait du taff en plus pour rien quand on sait bien ce qu'on fait derrière et qu'on part du principe qu'on ne fait jamais d'erreur. Moi c'est pas mon cas xD
    Pardon, je voulais parler de i_1D_deallocate ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void i_1D_deallocate( int *p )
    {
        if ( p ) { free( p ), p = NULL; }
    }
    En revanche, ne pas initialiser la mémoire allouée est typiquement dans l'esprit C. Tu ne repères pas forcément plus vite des erreurs et ça peut éventuellement en cacher si 0 est une valeur acceptable. Après c'est une question de style et/ou de goûts, initialiser parfois pour rien des tableaux de grandes tailles n'est que perte de temps. Bon tu me diras que calloc le fait mais en même temps le c de calloc signifie clear → Memory ALLOCation, Clear ALLOCation, RE ALLOCation …

    Edit: la notion de 32/64 bits et la taille de size_t tient surtout à la manière dont tu compiles.
    Si tu compiles un programme en 32 bits, il tournera aussi bien sur win32 et win64 mais n'aura accès qu'au 4Go (-1 ou 2 Go pour l'OS) → size_t aura 4 octets de large.
    Si tu compiles un programme en 64 bits, il ne tournera que sur win64 et aura accès à bien plus de mémoire → size_t aura 8 octets de large.
    Ce n'est pas l'OS qui fait tout, mais la manière de compiler. Si ton size_t fait 32 bits sur ton windows c'est que tu compiles en 32 bits.

  8. #8
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Comme quoi y'en avait des choses à redire ! Je vais pouvoir modifier tout ça et merci pour vos interventions.
    Je vais pouvoir m'essayer à ces fameuses macros aussi.

    Et concernant le fait de repasser les pointeurs à NULL après leur libération, c'est pour éviter le phénomène de "dangling pointer" qui implique que pour une raison x ou y si le pointeur libéré venait à être accédé, il lirait ou réécrirait à un endroit aléatoire de la mémoire. Alors que passé à NULL, c'est plantage direct, au moins c'est clair.
    Et je m'étais fais rappeler à l'ordre à l'époque à ce sujet par Medinoc ou Emmanuel Delahayes. Après, je n'exclus pas mal l'utiliser, il parlait peut être de faire ceci dans un cas spécifique, subtilité que je n'aurais pas appréhendée.

  9. #9
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Citation Envoyé par picodev Voir le message
    [...]
    Pardon, je voulais parler de i_1D_deallocate ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void i_1D_deallocate( int *p )
    {
        if ( p ) { free( p ), p = NULL; }
    }
    [...]
    Citation Envoyé par darkwall_37 Voir le message
    Comme quoi y'en avait des choses à redire ! Je vais pouvoir modifier tout ça et merci pour vos interventions.
    Je vais pouvoir m'essayer à ces fameuses macros aussi.

    Et concernant le fait de repasser les pointeurs à NULL après leur libération, c'est pour éviter le phénomène de "dangling pointer" qui implique que pour une raison x ou y si le pointeur libéré venait à être accédé, il lirait ou réécrirait à un endroit aléatoire de la mémoire. Alors que passé à NULL, c'est plantage direct, au moins c'est clair.
    Et je m'étais fais rappeler à l'ordre à l'époque à ce sujet par Medinoc ou Emmanuel Delahayes. Après, je n'exclus pas mal l'utiliser, il parlait peut être de faire ceci dans un cas spécifique, subtilité que je n'aurais pas appréhendée.
    Cela peut avoir un intérêt mais que tu le mettes à NULL ou pas la valeur du pointeur avec lequel tu appelles la fonction ne sera pas changée, en C les paramètres sont toujours passés par copie. Pour que cela ait un intérêt tu pourrais essayer un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void i_1D_deallocate( int **p )
    {
        if ( p && *p ) {
            free( *p );
            *p = NULL;
        }
    }
    mais ça rajoute une indirection.

  10. #10
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 510
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 510
    Par défaut
    Citation Envoyé par darkwall_37 Voir le message
    Pourquoi dans i_1D_allocate, p=NULL est inutile? Enfin l'est-ce vraiment ? Ça mange pas de pain quoi, et ça m'arrache les yeux d'écrire int *p;
    Dans ce cas, tu peux remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int *p = NULL;
    if ( ( p = (int*)malloc( p_sz*sizeof(int) ) ) )
    {
        // ...
    par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int *p = (int*)malloc( p_sz*sizeof(int) );
    if ( p )
    {
        // ...
    Citation Envoyé par darkwall_37 Voir le message
    Est ce que la présence des \ est normal ?
    Oui. C'est pour que la définition de la macro prenne aussi en compte la ligne suivante.

    Citation Envoyé par darkwall_37 Voir le message
    Est-ce que tu voulais dire ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    typedef unsigned int uint;
    DEFINITION_1D_allocate(uint) // définit la fonction "uint* uint_1D_allocate(size_t)"
    à la place de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typedef unsigned uint;
    DEFINITION_1D_allocate(uint) // définit la fonction "uint* uint_1D_allocate(size_t)"
    unsigned, c'est pareil que unsigned int.
    De manière générale, dans les types suivants, on peut enlever les mots entre parenthèses :
    • (signed) char (EDIT : erreur signalée par picodev)
    • (signed) short (int)
    • (signed) int
    • (signed) long (int)
    • (signed) long long (int)
    • unsigned char
    • unsigned short (int)
    • unsigned (int)
    • unsigned long (int)
    • unsigned long long (int)

  11. #11
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Citation Envoyé par Pyramidev Voir le message
    [...]
    De manière générale, dans les types suivants, on peut enlever les mots entre parenthèses :
    • (signed) char
    • (signed) short (int)
    • (signed) int
    • (signed) long (int)
    • (signed) long long (int)
    • unsigned char
    • unsigned short (int)
    • unsigned (int)
    • unsigned long (int)
    • unsigned long long (int)
    char est un type particulier. Il ne fait ni partie des entiers signés ni partie des entiers non signé. Il peut suivant la plateforme et l'implémentation du compilateur avoir ou non une représentation signée.
    char, signed char et unsigned char sont trois types différents.

  12. #12
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 510
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 510
    Par défaut
    Citation Envoyé par picodev Voir le message
    char est un type particulier. Il ne fait ni partie des entiers signés ni partie des entiers non signé. Il peut suivant la plateforme et l'implémentation du compilateur avoir ou non une représentation signée.
    char, signed char et unsigned char sont trois types différents.
    Au temps pour moi.

    char - type for character representation. Equivalent to either signed char or unsigned char (which one is implementation-defined and may be controlled by a compiler commandline switch), but char is a distinct type, different from both signed char both unsigned char
    Source : http://en.cppreference.com/w/c/langu...haracter_types

Discussions similaires

  1. [Dates] fonctions pour manipuler les temps
    Par xess91 dans le forum Langage
    Réponses: 20
    Dernier message: 18/04/2009, 23h10
  2. Réponses: 9
    Dernier message: 02/05/2007, 14h59
  3. Réponses: 8
    Dernier message: 29/06/2006, 15h37
  4. Fonction standard pour dédoublonner une liste ?
    Par ecocentric dans le forum Général Python
    Réponses: 3
    Dernier message: 22/08/2005, 10h41
  5. fonction c pour manipuler la structure date
    Par thomas_b dans le forum Windows
    Réponses: 4
    Dernier message: 28/07/2004, 16h28

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