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 :

La différence entre NULL et zéro


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Par défaut La différence entre NULL et zéro
    Bonjour,

    Soit un pointeur sur donnée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    typedef struct A
    { int i ;
      char [10] z; 
    } A ;
     
    A * a = (A*) malloc( sizeof(A) ) ;
    free( a ) ;
    a = 0 ;
    // ou a = NULL;
    Y-a-t-il une différence entre NULL et zéro ? Dans un environnement 32 bits, bien entendu.

    Salut.

  2. #2
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    La norme du langage C n'assure pas que NULL vaudra zéro (mais là, il faut que je vérifie, et j'ai pas le courage de me plonger dans la norme maintenant). NULL doit correspondre à une adresse invalide. Toutefois, sur la plupart des implantations que je connaisse, NULL est défini comme (void *) 0. Il s'agit donc d'un pointeur alors que 0 est une valeur de type int.

    Pour des questions de portabilité, initialiser un pointeur à NULL est une manière de dire: "cette adresse ne pointe pas sur une zone valide". En plus, NULL a l'avantage d'être une valeur testable, et permet ainsi d'examiner la validité de la valeur contenue par un pointeur.

    En résumé: si tu veux écrire du code portable, il est recommandé de ne faire aucune supposition quand à la valeur de NULL.

    En ce qui concerne ton morceau de code ci-dessus, il est générallement recommandé de ne pas caster la valeur de retour de malloc(). Par ailleurs, il y a une erreur de syntaxe dans la déclaration du tableau z, et la valeur de retour de malloc n'est pas testée...
    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
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct A_
    {
        int i ;
        char z[10];
    } A_s;
     
    int main(void)
    {
        /* Le cast de malloc() est déconseillé */
        A_s *a = malloc(sizeof *a);
        /* TOUJOURS vérifier la valeur de retour de malloc */
        if (a != NULL)
        {
            /* Des traitements faisant appel à a */
     
            free((void *) a), a = NULL;
        }
        else
        {
            fprintf(stderr, "L'allocation a échoué!\n");
            exit(EXIT_FAILURE);
        }
     
        return EXIT_SUCCESS;
    }

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  3. #3
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par mujigka
    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
    <...>
       if (a != NULL)
        {
            /* Des traitements faisant appel à a */
     
            free((void *) a), a = NULL;
        }
        else
        {
            fprintf(stderr, "L'allocation a échoué!\n");
            exit(EXIT_FAILURE);
        }
     
        return EXIT_SUCCESS;
    }
    Pourquoi rompre l'harmonie de la programmation structurée ? Tu ne te rends pas compte des conséquences cosmologiques que ça entraine... Moi, ça m'empêche de dormir en tout cas...

    Et pourquoi un cast pour free () ? Il n'est pas plus utile que celui du retour de malloc()...
    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct
    {
        int i ;
        char z[10];
    } 
    A_s;
     
    int main (void)
    {
       int ret = EXIT_SUCCESS;
       A_s *a = malloc (sizeof *a);
     
       if (a != NULL)
       {
          /* Des traitements faisant appel à a */
     
          free (a), a = NULL;
       }
       else
       {
          fprintf(stderr, "L'allocation a échoue!\n");
          ret = EXIT_FAILURE;
       }
     
       return ret; 
    }

  4. #4
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Pourquoi rompre l'harmonie de la programmation structurée ? Tu ne te rends pas compte des conséquences cosmologiques que ça entraine... Moi, ça m'empêche de dormir en tout cas...
    Parce que je n'ai pas réfléchi plus loin, et que c'est devenu chez moi une suite d'instruction idiomatique (c'est vrai que ça m'empêche de dormir, maintenant qu'on en parle...). Je vais corriger ma manière de faire.

    Citation Envoyé par Emmanuel Delahaye
    Et pourquoi un cast pour free () ? Il n'est pas plus utile que celui du retour de malloc()...
    Je ne sais plus pourquoi j'ai commencé à caster les paramètres que je passe à free(). Je crois que c'était sur conseil de mon compilateur. Bref, je n'y tiens pas plus que tant... Par contre, s'il n'est pas plus utile que le cast d'un retour de malloc(), il est moins dangereux. En effet, en cas d'oubli de l'inclusion de stdlib.h, caster le retour de malloc élimine la possibilité pour le compilateur de rapporter cet oubli, tandis que caster ou pas l'argument passé à free() ne change simplement rien. Au pire c'est inutile. Je vais suivre ton conseil et cacher ce cast que je ne saurais voir...

    Merci pour tout

    Thierry (qui progresse vite, mais à qui il faut expliquer longtemps)
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  5. #5
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Par défaut
    Bonjour,

    Mujigka écrit :

    En ce qui concerne ton morceau de code ci-dessus, il est générallement recommandé de ne pas caster la valeur de retour de malloc(). Par ailleurs, il y a une erreur de syntaxe dans la déclaration du tableau z, la valeur de retour de malloc n'est pas testée
    C' était tout simplement un exemple court , pas la peine de vérifier.

    A mon avis, une bibliothèque écrite en C, avec la convention du 0 à la place du NULL, pourrait fonctionner en C++, sauf si ...

    Salut.

  6. #6
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par dj.motte
    C' était tout simplement un exemple court , pas la peine de vérifier.
    Mais, c'est dans les exemples courts que se profilent déjà les bonnes habitudes

    Citation Envoyé par dj.motte
    A mon avis, une bibliothèque écrite en C, avec la convention du 0 à la place du NULL, pourrait fonctionner en C++, sauf si ...
    Avec NULL, ça fonctionne aussi, car NULL est défini comme 0 (et non (void *)0) sur la plupart des implantations C++ que je connaisse. Ne pas caster malloc() peut entrainer des problèmes en compilant le code à l'aide d'un compilateur C++. De toute manière, je suis partisan de compiler du code C avec un compilateur C, et de prévoir un fichier d'en-tête auto-démerdant permettant au fichier objet en question d'être lié à un projet C comme à un projet C++. Exemple de fichier d'en-tête adapté pour lier une bibliothèque écrite en C à un programme écrit en 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
    #ifndef H_TC_MONHEADER_20070218003822
    #define H_TC_MONHEADER_20070218003822
     
    #ifdef __cplusplus
    extern "C" {
    #endif
     
    void fonction1(void);
    int fonction2(int, int);
     
    #ifdef __cplusplus
    }
    #endif
     
    #endif /* guard H_TC_MONHEADER_20070218003822 */
    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  7. #7
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par mujigka
    Avec NULL, ça fonctionne aussi, car NULL est défini comme 0 (et non (void *)0) sur la plupart des implantations C++ que je connaisse.
    NULL doit être une constante entière en C++. (void*)0 est interdit (et ne fonctionnerait pas parce qu'il n'y a pas de conversion implicite de void* vers les autres types de pointeurs).

  8. #8
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Petit ajout, ne pas oublier que NULL doit être casté en un pointeur quand il sert d'argument à une fonction variadique ou à une fonction sans prototype. Les implémentations qui définissent NULL comme (void*) le font pour éviter de casser le code qui l'oublie, mais toutes ne sont pas dans ce cas.

  9. #9
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par dj.motte
    Soit un pointeur sur donnée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    typedef struct A
    { int i ;
      char [10] z; 
    } A ;
     
    A * a = (A*) malloc( sizeof(A) ) ;
    free( a ) ;
    a = 0 ;
    // ou a = NULL;
    Y-a-t-il une différence entre NULL et zéro ?
    Ici, non. Mais NULL a valeur documentaire dans un contexte pointeur, et il est préférable de l'utiliser dans ce cas là.

    On a pas le droit de l'utiliser ailleurs que dans un contexte pointeur. Par exemple :
    est faux (comportement indéfini)

    Rappel : Dans le code C que tu as posté, le cast est inutile.
    Dans un environnement 32 bits, bien entendu.
    "Irrelevent Captain !"
    --Spock in TOS

  10. #10
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Norme C99, article 6.3.2.3
    An integer constant expression with the value 0, or such an expression cast to type
    void *, is called a null pointer constant.55) If a null pointer constant is converted to a
    pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal
    to a pointer to any object or function.
    et
    Citation Envoyé par Norme C99, article 7.17
    NULL
    which expands to an implementation-defined null pointer constant;
    Oui, la norme assure que NULL sera remplacé par la valeur 0 ou (void *) 0.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  11. #11
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par mujigka
    et


    Oui, la norme assure que NULL sera remplacé par la valeur 0 ou (void *) 0.

    Thierry
    Ou 0L, (void*)0L, (42-21-21),... en pratique j'ai déjà vu le premier cas.

Discussions similaires

  1. [MySQL] Problème différenciation entre valeur null et zéro
    Par stefsas dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 08/03/2010, 16h44
  2. Différence entre chaine vide et chaine nulle
    Par brassouille dans le forum PL/SQL
    Réponses: 2
    Dernier message: 30/12/2008, 11h04
  3. [List] différence entre empty et null
    Par kaljerhom dans le forum Langage
    Réponses: 1
    Dernier message: 08/12/2008, 10h41
  4. Réponses: 14
    Dernier message: 12/11/2008, 19h01
  5. gerer la différence entre Null et '' dans un formulaire?
    Par XtofRoland dans le forum Langage
    Réponses: 7
    Dernier message: 21/02/2006, 12h45

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