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

  1. #1
    Membre confirmé
    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
    Points : 460
    Points
    460
    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;
    }
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

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

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    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
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 108
    Points
    6 108
    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 émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    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 confirmé
    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
    Points : 460
    Points
    460
    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
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  6. #6
    Membre confirmé
    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
    Points : 460
    Points
    460
    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 ?
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

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

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    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 confirmé
    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
    Points : 460
    Points
    460
    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.
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

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

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    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
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 108
    Points
    6 108
    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 émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    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
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 108
    Points
    6 108
    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

  13. #13
    Membre confirmé
    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
    Points : 460
    Points
    460
    Par défaut
    Messieurs bonjour,

    J'ai modifié le code selon vos remarques.
    Par contre je m'explique par pourquoi je suis obligé d'inclure stdbool.h dans le header pour que le type bool soit reconnu. Si je le fais dans le .c, il me dit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ||=== Build: Debug in LIBRARY (compiler: GNU GCC Compiler) ===|
    ptr.h|7|error: unknown type name 'bool'|

    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
    #ifndef PTR_H
    #define PTR_H
     
    #include <stdbool.h>
     
    void  i_1D_deallocate      ( int *p );
    int  *i_1D_allocate        ( size_t p_sz );
    bool  i_1D_realloc         ( int **p, size_t *p_sz, size_t new_sz );
    bool  i_1D_insert          ( int **p, size_t *p_sz, size_t offset, int v );
    int  *i_1D_extract         ( int *p, size_t p_sz, size_t i0, size_t i1, size_t *q_sz );
    bool  i_1D_split           ( int *p, size_t *p_sz, int **p1, size_t *p1_sz, int **p2, size_t *p2_sz, size_t offset );
    bool  i_1D_remove          ( int **p, size_t *p_sz, size_t offset );
    int  *i_1D_copy            ( int *p, size_t p_sz );
    bool  i_1D_replace         ( int *p0, size_t p0_sz, int *p1, size_t p1_sz );
    bool  i_1D_init            ( int *p, size_t p_sz, int v );
    int  *i_1D_rshift          ( int *p, size_t p_sz, size_t shift );
    int  *i_1D_lshift          ( int *p, size_t p_sz, size_t shift );
    bool  i_1D_rshift_self     ( int *p, size_t p_sz, size_t shift );
    bool  i_1D_lshift_self     ( int *p, size_t p_sz, size_t shift );
    void  i_1D_replace_partial ( int *p0, int *p1, size_t i_for_start, size_t i_for_end, size_t i_p0, size_t i_p1, short p0_sign, short p1_sign );
     
    #endif

    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 ); }
    }
     
    int *i_1D_allocate( size_t p_sz )
    {
        int *p = NULL;
        if ( ( p = malloc( p_sz*sizeof(*p) ) ) )
        {
            size_t i;
            for ( i=0 ; i<p_sz ; i++ )
                p[i] = 0;
        }
        return p;
    }
     
    bool i_1D_realloc( int **p, size_t *p_sz, size_t new_sz )
    {
        bool b = false;
        if ( *p && new_sz != 0 )
        {
            int *p_realloc = NULL;
            if ( ( p_realloc = realloc( (*p), new_sz*sizeof(*p_realloc) ) ) )
            {
                (*p) = p_realloc;
                size_t i;
                for ( i=*p_sz ; i<new_sz ; i++ )
                    (*p)[i] = 0;
     
                *p_sz = new_sz;
                b = true;
            }
        }
        return b;
    }
     
    bool i_1D_insert( int **p, size_t *p_sz, size_t offset, int v )
    {
        bool b = false;
        if ( *p && 0 <= offset && offset < *p_sz+1 )
        {
            if ( i_1D_realloc( p, p_sz, *p_sz+1 ) == true )
            {
                size_t 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, size_t p_sz, size_t i0, size_t i1, size_t *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;
    }
     
    bool i_1D_split( int *p, size_t *p_sz, int **p1, size_t *p1_sz, int **p2, size_t *p2_sz, size_t offset )
    {
        bool 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, size_t 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;
    }
     
    bool i_1D_remove( int **p, size_t *p_sz, size_t offset )
    {
        bool b = false;
        if ( *p && 0 <= offset && offset < *p_sz )
        {
            size_t q_sz = *p_sz; size_t index = 0;
            int *q = i_1D_copy( (*p), *p_sz );
            if ( i_1D_realloc( p, p_sz, *p_sz-1 ) == true )
            {
                size_t i;
                for ( i=0 ; i<q_sz ; i++ )
                {
                    if ( i != offset )
                        (*p)[index] = q[i], index++;
                }
                i_1D_deallocate( q );
                b = true;
            }
        }
        return b;
    }
     
    bool i_1D_replace( int *p0, size_t p0_sz, int *p1, size_t p1_sz )
    {
        bool 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;
    }
     
    bool i_1D_init( int *p, size_t p_sz, int v )
    {
        bool b = false;
        if ( *p && p_sz > 0 )
        {
            size_t 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, size_t i_for_start, size_t i_for_end, size_t i_p0, size_t i_p1, short p0_sign, short p1_sign )
    {
       size_t 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, size_t p_sz, size_t 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, size_t p_sz, size_t 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;
    }
     
    bool i_1D_rshift_self( int *p, size_t p_sz, size_t shift )
    {
        bool 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;
    }
     
    bool i_1D_lshift_self( int *p, size_t p_sz, size_t shift )
    {
        bool 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;
    }
    @picodev
    mais ça rajoute une indirection.
    Qu'entends tu par indirection ?

    vrai n'implique t-il pas que est vrai ? (la réciproque étant fausse)

    Concernant le cast de malloc, je dois dire que même en école d'ingé on m'a appris à caster les malloc et cela par un prof qui en plus a fait une thèse sur une problématique XY en C. A priori, quelque chose qu'il devrait savoir ?

    @pyramidev

    Je viens de tester les macros et c'est vraiment génial alors un énorme merci pour cette info
    Je compte bien intégrer les flottants également.
    Est-ce que je dois différencier les macros pour les entiers et flottants ?
    Où il est permit d'initialiser un entier de la sorte int a = 0.; Ainsi, je n'aurais à priori plus besoin de faire de double macro pour les fonctions qui feraient intervenir ce genre d'opérations. (Oui je sais, j'essaye toujours d'en faire le moins, mais les programmeurs (les vrais et les faux comme moi) ne sont-il pas à fortiori les plus gros feignants de la planète ? Travailler plus pour travailler moins n'est ce pas ).
    Où plus simplement, il y a peut être un niveau de granularité supérieur dans la macro qui permet de gérer directement ce genre de cas ?

    merci:
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  14. #14
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 470
    Points : 6 108
    Points
    6 108
    Par défaut
    Citation Envoyé par darkwall_37 Voir le message
    Par contre je m'explique par pourquoi je suis obligé d'inclure stdbool.h dans le header pour que le type bool soit reconnu.
    C'est normal. bool doit être défini avant d'être utilisé. Or, ton header utilise bool. Donc, ton header doit inclure <stdbool.h>.

    D'ailleurs, maintenant que j'y pense, dans ptr.c, il est préférable de changer l'ordre des inclusions :
    Maintenant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #include <stdio.h>  // entre autres, définit size_t (si pas déjà défini)
    #include <stdlib.h> // entre autres, définit size_t (si pas déjà défini)
    #include "ptr.h"
    Après :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #include "ptr.h" // devrait être en premier ; comme ça, si ça compile,
                     // on sait que "ptr.h" inclut tout ce qu'il faut pour compiler
    #include <stdio.h>
    #include <stdlib.h>
    Normalement, le compilateur devrait râler en disant qu'il ne connaît pas size_t dans ptr.h.
    Pour corriger, il suffira d'ajouter, par exemple, #include <stddef.h> (qui définit size_t) dans ptr.h.

    Sinon, l'oubli sera caché à court terme et le compilateur râlera un autre jour, dès que tu incluras quelque part ptr.h sans inclure au préalable au moins un entête qui définit size_t.

    Citation Envoyé par darkwall_37 Voir le message
    Concernant le cast de malloc, je dois dire que même en école d'ingé on m'a appris à caster les malloc et cela par un prof qui en plus a fait une thèse sur une problématique XY en C. A priori, quelque chose qu'il devrait savoir ?
    Le cast de malloc, c'est bien si on veut faire un code qui compile aussi en C++.
    Sinon, c'est redondant.

    Ou alors, ton prof est victime du poids des habitudes.
    En C ANSI (1989), malloc retourne un void* et n'a pas besoin d'être casté.
    Mais, avant, malloc retournait un char* et avait besoin d'être casté.

    Citation Envoyé par darkwall_37 Voir le message
    Je compte bien intégrer les flottants également.
    Est-ce que je dois différencier les macros pour les entiers et flottants ?
    Où il est permit d'initialiser un entier de la sorte int a = 0.;
    Pas besoin de différencier les macros pour les entiers et flottants.
    int a = 0.; et double a = 0; sont tous les deux permis.

  15. #15
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par darkwall_37 Voir le message
    Qu'entends tu par indirection ?
    C'est le terme employé pour indiquer le fait d'avoir une étoile de plus que le type que tu manipules. Si ta fonction doit manipuler un int, elle recevra un "int étoile". Si elle doit manipuler un "truc étoile" elle recevra un "truc étoile étoile".
    Et si on parle de "double indirection" alors c'est pour "deux étoiles de plus". Et même cheminement de pensée pour triple/quadruple/quintuple etc... indirection.

    Citation Envoyé par darkwall_37 Voir le message
    vrai n'implique t-il pas que est vrai ? (la réciproque étant fausse)
    Absolument pas. Le C ne fait aucune vérification implicite.

    Citation Envoyé par darkwall_37 Voir le message
    Concernant le cast de malloc, je dois dire que même en école d'ingé on m'a appris à caster les malloc et cela par un prof qui en plus a fait une thèse sur une problématique XY en C. A priori, quelque chose qu'il devrait savoir ?
    Vaste polémique. Certains sont pour et on des arguments valable dans ce sens, certains sont contre et ont aussi d'autres arguments tout aussi valables dans ce sens. C'est donc à toi de choisir en fonction des avantages et inconvénients des deux façons de faire. Mais ce n'est pas parce que M. Truc à fait un thèse que ses arguments sont plus pertinents/profonds/efficaces que M. Chose qui n'en a pas fait. Surtout que la thèse en question n'a rien à voir avec les effets du cast/non cast du malloc...

    Citation Envoyé par darkwall_37 Voir le message
    ...mais les programmeurs (les vrais et les faux comme moi) ne sont-il pas à fortiori les plus gros feignants de la planète ? Travailler plus pour travailler moins n'est ce pas ).
    Exactement. C'est plus une question d'efficacité que de fainéantise. Un code bien factorisé c'est un code plus facile à comprendre et à faire évoluer.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  16. #16
    Membre confirmé
    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
    Points : 460
    Points
    460
    Par défaut
    Salut Sve@r,

    Je ne pensais pas à une vérification implicite.
    Par exemple si on a un int **p ( tableau à 2D p[x][y] ) le fait que *p soit valide n'implique t'il pas que p le soit également ? De la même manière que pour arriver au sommet d'une pyramide, il faut passer par sa base. Donc si on arrive au sommet c'est que la base existe.
    C'est plutôt comme ça que je le voyais. Je ne suis pas sur de bien présenter la chose mais je pense que tu comprends là où je veux en venir.

    Si l'on suppose qu'il s'agit d'une indirection '**' à priori il ne faudrait tester que *p puisque p n'est pas alloué, il permet de passer que l'adresse de *p ?
    Alors que sans indirection, il faudrait tester p & *p même si je croyais que *p vrai implique "implicitement" que p est vrai également.

    Je n'entendais pas que le fait d'avoir fait une thèse lui donnait légitimité mais plutôt qu'il aurait dû être à fortiori au courant et qu'il avait au moins le devoir de nous expliquer le problème.

    Exactement. C'est plus une question d'efficacité que de fainéantise. Un code bien factorisé c'est un code plus facile à comprendre et à faire évoluer.
    C'est le serpent qui se mort la queue car pour moi un bon feignant se doit d'être efficace xD.

    Effectivement pour bool... Ok je sors

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Pas besoin de différencier les macros pour les entiers et flottants. 
    int a = 0.; et double a = 0; sont tous les deux permis.
    Il me semblait avoir eu un problème à ce sujet une fois, mais en fait j'ai fais l'amalgame avec ce problème : float b = 2/3 et float b =2/3.
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

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

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    Par défaut
    Citation Envoyé par darkwall_37 Voir le message
    @picodev

    Qu'entends tu par indirection ?
    @Svear a tout bien expliqué.

    Citation Envoyé par darkwall_37 Voir le message
    vrai n'implique t-il pas que est vrai ? (la réciproque étant fausse)
    Avant même de vérifier que *p soit valide il faut s'assurer que l'est. L'avantage avec l'opérateur && est que la seconde opérande n'est évaluée uniquement lorsque la première est vrai, vrai pour un pointeur signifie «n'est pas NULL», faux signifie «est NULL». Cette écriture permet uniquement de s'assurer de ne pas déréférencer un pointeur NULL, mais en aucun cas ne s'assure que la zone pointée est valide et/ou contient des données correctes.

    Citation Envoyé par darkwall_37 Voir le message

    Concernant le cast de malloc, je dois dire que même en école d'ingé on m'a appris à caster les malloc et cela par un prof qui en plus a fait une thèse sur une problématique XY en C. A priori, quelque chose qu'il devrait savoir ?
    Oui sans doute. Une des choses qu'on apprend en premier est qu'il y a toujours plus à apprendre et qu'on ne sait pas tout. Après tu as
    soit une affirmation avec des arguments qui expliquent le pourquoi de la proposition →ne pas caster les mallocs car 1. ça alourdit l'écriture en la rendant plus compliquée et plus prone aux erreurs 2. ça peut cacher des erreurs lors de l'édition des liens 3. ce n'est qu'un reliquat vieux de plus de 25 ans … 4. tu n'as pas d'erreurs si par mégarde tu compiles avec un compilateur c++ 5. etc
    soit tu as une affirmation avec un argument d'autorité → il a fait une thèse donc il détenteur d'un savoir qui devrait faire autorité.
    Quoi qu'il en soit tu as le choix, tu ne seras ni pendu ni brûlé vif pour avoir casté les mallocs.

  18. #18
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par darkwall_37 Voir le message
    Il me semblait avoir eu un problème à ce sujet une fois, mais en fait j'ai fais l'amalgame avec ce problème : float b = 2/3 et float b =2/3.
    Aucune différence entre les deux écritures => dans les 2 cas, b vaut 0. Parce que l'opération est faite dans le type le plus large des opérandes utilisés et qu'ici, le type le plus large est int (et mettre ou ne pas mettre d'espace avant le "=" ne change rien).
    Si tu veux que b ait le bon résultat, il faut impérativmeent placer un float dans l'opération donc écrire explicitement float b=2.0/3 ou bien float b=2/3.0.

    Et attention aux erreurs d'interprétation. J'ai bien écrit "opérandes utilisés" et non "opérandes présents". Si par exemple tu écris float b=2/3 + 5.0, ben malgré la présence du float "5.0", l'opération de division ne traitant que 2 et 3 se fera là encore en int.

    PS: en relisant je me dis que le point de ta seconde écriture "float b =2/3." pourrait ne pas être un point de ponctuation dans ta phrase mais un point de flottant et que tu aies alors voulu montrer float b=2/3..
    Dans ce cas, pour éviter toute erreur d'interprétation du forum, essaye d'écrire les choses en entier "3.0" au lieu de "3.", éventuellement de rajouter le point-virgule final nécessaire à toute instruction C float b=2/3.; et d'encadrer tes courts exemples de codes de balise "[ c]" et "[ /c]"...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  19. #19
    Membre confirmé
    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
    Points : 460
    Points
    460
    Par défaut
    Salut,

    Concernant la déclaration des fonctions dans le header définies par les macros/DEF dans le .c, est-ce que je dois les déclarer de la sorte dans le header ou il y a moyen de factoriser ?

    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    #ifndef PTR_H
    #define PTR_H
     
    #include <stddef.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef signed char sc;
    typedef int short s;
    typedef int i;
    typedef long l;
    typedef long long ll;
    typedef char c;
    typedef unsigned char uc;
    typedef unsigned short us;
    typedef unsigned ui;
    typedef unsigned long ul;
    typedef unsigned long long ull;
    typedef float f;
    typedef double d;
    typedef long double ld;
     
    void sc_1D_deallocate( sc *p );
    void s_1D_deallocate( s *p );
    void i_1D_deallocate( i *p );
    void l_1D_deallocate( l *p );
    void ll_1D_deallocate( ll *p );
    void c_1D_deallocate( c *p );
    void uc_1D_deallocate( uc *p );
    void us_1D_deallocate( us *p );
    void ui_1D_deallocate( ui *p );
    void ul_1D_deallocate( ul *p );
    void ull_1D_deallocate( ull *p );
    void f_1D_deallocate( f *p );
    void d_1D_deallocate( d *p );
    void ld_1D_deallocate( ld *p );
    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
     
    #include "ptr.h"
     
    #define DEF_1D_deallocate(type) \
    void type##_1D_deallocate( type *p ) \
    { \
        if ( p ) { free( p ); } \
    }
     
    DEF_1D_deallocate(sc);
    DEF_1D_deallocate(s);
    DEF_1D_deallocate(i);
    DEF_1D_deallocate(l);
    DEF_1D_deallocate(ll);
    DEF_1D_deallocate(c);
    DEF_1D_deallocate(uc);
    DEF_1D_deallocate(us);
    DEF_1D_deallocate(ui);
    DEF_1D_deallocate(ul);
    DEF_1D_deallocate(ull);
    DEF_1D_deallocate(f);
    DEF_1D_deallocate(d);
    DEF_1D_deallocate(ld);
    Merci d'avance !
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  20. #20
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    J'ai peut-être raté un épisode de la conversation, mais pourquoi faire ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    typedef signed char sc;
    typedef int short s;
    typedef int i;
    typedef long l;
    typedef long long ll;
    typedef char c;
    typedef unsigned char uc;
    typedef unsigned short us;
    typedef unsigned ui;
    typedef unsigned long ul;
    typedef unsigned long long ull;
    typedef float f;
    typedef double d;
    typedef long double ld;
    ? Je trouve que ça tue la lisibilité de la suite ! Si je comprend bien, c'est nécessaire pour l'utilisation de la macro, mais cela oblige l'utilisateur à mémoriser les différentes abréviations.


    PS: en relisant je me dis que le point de ta seconde écriture "float b =2/3." pourrait ne pas être un point de ponctuation dans ta phrase mais un point de flottant et que tu aies alors voulu montrer float b=2/3..
    Dans ce cas, pour éviter toute erreur d'interprétation du forum, essaye d'écrire les choses en entier "3.0" au lieu de "3.", éventuellement de rajouter le point-virgule final nécessaire à toute instruction C float b=2/3.; et d'encadrer tes courts exemples de codes de balise "[ c]" et "[ /c]"...
    Pour ceux qui ne le savent pas, notez qu'en plus des balises [CODE][/CODE] que vous connaissez tous, il existe [CODEinline][/CODEinline] et sa version abrégée [c][/C]. Elle donne ceci par exemple String h = "hello, world";. La casse ne compte pas pour écrire les balises. Enfin, il existe la balise [noparse][/noparse] !

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