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 :

Pointeur Null pointe où ?


Sujet :

C

  1. #21
    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 |PaRa-BoL
    Et /dev/null c'est un trou noir ?
    Sans rapport avec NULL... au sens du langage C.

    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++

    +

  2. #22
    Blue_Strike
    Invité(e)
    Par défaut
    bonsoir,

    mujigka a écrit :
    Citation:
    |PaRa-BoL a écrit :
    Et /dev/null c'est un trou noir ?
    Sans rapport avec NULL... au sens du langage C.

    Thierry
    oui, ça n'a rien à avoir avec le problème de la discussion posé sur "NULL"..

    @Emmanuel Delahaye : bah tu as la répense concernant ta question ! :
    oui biensur, je précise..

    - IDE : turbo C++ v4.5 (sous win biensur)
    - OS : win XP SP2
    - j'ai rien changé comme réglages, il est installé par défaut..
    ++

  3. #23
    Membre averti
    Inscrit en
    Octobre 2006
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 20
    Par défaut
    Citation Envoyé par Blue_Strike
    bonsoir,



    la phrase en rouge dépend de la technologie de la mémoire elle meme. Enfait il est 'interdit' de déférérencer un pointeur valant NULL (puisqu'il est Null ) ; Mais en réalité, losque le pointeur vaut Null, il pointe sur une zone spéciale de la mémoire dépendant de sa technologie comme j'avais dis (d'où à lire la phrase rouge) .. cette zone n'est pas utilisable comme une simple case mémoire, elle est morte, et seul le constructeur connaît son emplacement.. c'est pourquoi on ne doit jamais déférérencer un pointeur valant NULL



    ++

    il ne pointe nul part :autrement dit y a pas de case memoire reservée pour un pointeur NULL.

    mais plutot un pointeur NULL vaut en principe 0 mais cette case n'est pas reservée pour les variable.

    important: on sait q'un pointeur vaut NULL par sa valeur (0)
    pas par ce que contient l'adresse (0).

  4. #24
    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 denoo
    important: on sait q'un pointeur vaut NULL par sa valeur (0)
    pas par ce que contient l'adresse (0).
    +1

  5. #25
    Membre émérite Avatar de |PaRa-BoL
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 738
    Par défaut
    stddef.h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #if defined(__cplusplus)
    #define NULL 0
    #else
    #define NULL ((void *)0)

  6. #26
    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 |PaRa-BoL
    stddef.h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #if defined(__cplusplus)
    #define NULL 0
    #else
    #define NULL ((void *)0)
    Oui, on le sait bien. Et ?

  7. #27
    Membre émérite Avatar de |PaRa-BoL
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 738
    Par défaut
    Et rien, je confirme juste par un quote le message précédent...

  8. #28
    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 |PaRa-BoL
    Et rien, je confirme juste par un quote le message précédent...
    Alors il faut apprendre à citer :

  9. #29
    Blue_Strike
    Invité(e)
    Par défaut
    bonsoir,

    denoo a écrit :
    il ne pointe nul part :autrement dit y a pas de case memoire reservée pour un pointeur NULL.

    mais plutot un pointeur NULL vaut en principe 0 mais cette case n'est pas reservée pour les variable.

    important: on sait q'un pointeur vaut NULL par sa valeur (0)
    pas par ce que contient l'adresse (0).
    mais elle existe qd même !
    +9999
    ça c'est au niveau soft ! je parle réellement qu'est ce qui se passe, vous me comprenez ?! (niveau architecture plus que soft)
    bon j'ai une question : si un pointeur pointe sur une variable int par exemple, l'adresse de ce pointeur se trouve où ? c'est à dire où elle est stockée ?
    et si un pointeur vaut NULL, autrement dit (0), est ce que celà est l'équivalent à 0000x0000 ??

    @denoo : tu appelle quoi une case qui n'est pas reservée pour les variables ?

    ++

  10. #30
    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 Blue_Strike
    mais elle existe qd même !
    Pas forcément. Ca dépend des machines. Et si il y a une MMU ou pas etc. Le 0 de la MMU n'est pas le 0 physique...

    Il peut aussi en exister un grand nombre, comme en x86 mode réel modèle de mémoire small (DS:0000) avec DS valant de 0 à 0xFFFF
    bon j'ai une question : si un pointeur pointe sur une variable int par exemple, l'adresse de ce pointeur se trouve où ? c'est à dire où elle est stockée ?
    Le pointeur étant une variable, il a une adresse. Une adresse est une expression constante. Elle n'est pas 'stockée'. Vu de l'assembleur (langage machine), c'est une valeur immédiate.
    et si un pointeur vaut NULL, autrement dit (0), est ce que celà est l'équivalent à 0000x0000 ??
    En valeur, oui, en adresse physique, non, pas automatiquement. C'est vrai dans certains cas.
    @denoo : tu appelle quoi une case qui n'est pas reservée pour les variables ?
    De la mémoire libre (heap ou tas ou free store). C'est la zone allouable par malloc().

  11. #31
    Blue_Strike
    Invité(e)
    Par défaut
    Emmanuel Delahaye a écrit :

    Citation:
    Blue_Strike a écrit :
    mais elle existe qd même !
    Pas forcément. Ca dépend des machines. Et si il y a une MMU ou pas etc. Le 0 de la MMU n'est pas le 0 physique...
    +1

    Il peut aussi en exister un grand nombre, comme en x86 mode réel modèle de mémoire small (DS:0000) avec DS valant de 0 à 0xFFFF
    ça existe en motorola aussi (68000)..

    Le pointeur étant une variable, il a une adresse. Une adresse est une expression constante. Elle n'est pas 'stockée'. Vu de l'assembleur (langage machine), c'est une valeur immédiate.
    oui mais même la valeure immédiate est "stocké" disons sauvegardée qque part non ?! dans la RAM par exeple, sinon, si tu mets :
    int *k;
    int i=59;
    *k=i;
    printf("%p",k); => ça doit afficher l'adresse de i, mais qui est reprentée par k, alors là, comment le compilateur trouve la valeur? ou coment il a connu que k est l'adresse de i ? sûrement qque chose a changé en executant cette instruction : *k=i;

    Ok pour le reste

    ++

  12. #32
    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 Blue_Strike
    bonsoir,


    mais elle existe qd même !
    +9999
    ça c'est au niveau soft ! je parle réellement qu'est ce qui se passe, vous me comprenez ?! (niveau architecture plus que soft)
    bon j'ai une question : si un pointeur pointe sur une variable int par exemple, l'adresse de ce pointeur se trouve où ? c'est à dire où elle est stockée ?
    et si un pointeur vaut NULL, autrement dit (0), est ce que celà est l'équivalent à 0000x0000 ??

    @denoo : tu appelle quoi une case qui n'est pas reservée pour les variables ?

    ++
    Soit ce petit programme:
    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
    #include <stdio.h>
    #include <stdlib.h>
     
    void affiche_pile(void)
    {
        int a = 10;
        int *pa = &a;
        int *pb = NULL;
     
        printf("Adresse de a: %p\tValeur de a: %d\n", (void *)&a, a);
        printf("Adresse de pa: %p\tValeur de pa: %p\n", (void *)&pa, (void *)pa);
        printf("Adresse de pb: %p\tValeur de pb: %p (i.e %ld)\n", (void *)&pb,
            (void *)pb, (long)pb);
    }
     
    int main(void)
    {
        affiche_pile();
     
        return EXIT_SUCCESS;
    }
    Il produit la sortie suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    thierry@mujigka:~/forum$ ./forum
    Adresse de a: 0xbfaec314        Valeur de a: 10
    Adresse de pa: 0xbfaec310       Valeur de pa: 0xbfaec314
    Adresse de pb: 0xbfaec30c       Valeur de pb: (nil) (i.e 0)
    On y voit que les valeurs de a, pa et pb sont stockées sur la pile aux adresses 0xbfaec314, 0xbfaec310 et 0xbfaec30c respectivement. On voit très clairement que pa pointe sur a. La valeur stockée dans pb à l'adresse 0xbfaec30c est NULL, c'est à dire 0x00000000 sur ma machine où les pointeurs sont codés sur 32 bits. Si tu regarde le code assembleur généré (dans mon cas par gcc), tu peux voir que ce ne sont que des valeurs binaires codées sur 4 octets.

    Voici le code assembleur GNU correspondant à la fonction affiche_pile():
    Code gas : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    affiche_pile:
            pushl   %ebp
            movl    %esp, %ebp
            subl    $40, %esp
            # Ici, on stocke la valeur 10 dans a
            movl    $10, -4(%ebp)
            # On calcul l'adresse de a et on stocke cette valeur dans le 
            # registre EAX (architecture IA-32)
            leal    -4(%ebp), %eax
            # On stocke l'adresse de a dans pa
            movl    %eax, -8(%ebp)
            # Et maintenant, on stocke la valeur 0 (NULL) dans pb
            movl    $0, -12(%ebp)
            #...
    Tu peux voir qu'il n'y a pas de différence entre la valeur 10 stockée dans a, qui dans le programme C est de type int, et la valeur 0 (i.e. NULL) stockée dans pb. Autrement dit, le types des variables n'existe plus dans ce code assembleur. Rien ne dit que la valeur à l'adresse -12(%ebp) (qui correspond ici à pb) est un pointeur et que cette valeur correspond à une adresse qui peut être déréférencée. C'est le compilateur qui décide si on peut déréférencer cette valeur, et génère le cas échéant le code assembleur permettant d'accéder à la valeur située à l'adresse stockée dans pb. Dans le cas, du pointeur NULL, le compilateur sait que ce n'est pas une adresse valable et son comportement est indéterminé.

    Pour conclure, tout ceci fait apparaître que NULL correspond à la valeur 0x00000000 (sur mon PIII) et que cette valeur est dans le cas de notre exemple, stockée sur la pile. Ainsi NULL n'est qu'une valeur comme la valeur 10 stockée dans la variable a, mais ne pointe NULLE PART. C'est le compilateur qui décide si cette valeur peut représenter une adresse mémoire ou pas (lr compilateur sait que 10 n'est pas une adresse, car la valeur stockée dans a est de type int). Dans le cas de NULL, cela ne représente pas une adresse valable. Par suite, la question de savoir où pointe NULL est un non sens.

    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++

    +

  13. #33
    Membre expérimenté
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Par défaut
    Citation Envoyé par Blue_Strike
    int *k;
    int i=59;
    *k=i;
    printf("%p",k);
    Attend toi à des surprises

  14. #34
    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 Blue_Strike
    oui mais même la valeure immédiate est "stocké" disons sauvegardée qque part non ?!
    Elle est écrite en dur dans le code machine. Il y a des champs de bits pour ça dans les instructions. Ouvrir son livre d'assembleur...
    dans la RAM par exeple, sinon, si tu mets :
    int *k;
    int i=59;
    *k=i;
    Comme dirait ma fille 'explosition ' k est un pointeur non initialisé, son déréférencement invoque un comportement indéterminé. Tout le raisonnement de la suite est faux.

  15. #35
    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 Blue_Strike
    mais même la valeure immédiate est "stocké" disons sauvegardée qque part non ?! dans la RAM par exeple, sinon, si tu mets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int *k;
    int i=59;
    *k=i;
    printf("%p",k); => ça doit afficher l'adresse de i, mais qui est reprentée par k, alors là, comment le compilateur trouve la valeur? ou coment il a connu que k est l'adresse de i ? sûrement qque chose a changé en executant cette instruction : *k=i;

    Ok pour le reste

    ++
    J'ai l'impression que la manipulation des pointeurs n'est pas très claire pour toi. Dans le micro bout de code ci-dessus, jamais le pointeur k ne reçois l'adresse de i. *k = i; correspond à un déréférencement de k (non initialisé i.e. comportement indéfini) pour stoquer la valeur de i à l'adresse contenue dans k. C'est pas du tout ce que tu décris. Regarde mon dernier post et tu comprendras mieux...
    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    void comprendre_mem(void)
    {
    	int i = 59;
    	int *k;
            /* Ici, k reçoit l'adresse de i de manière explicite */
    	k = &i;
    	printf("L'adresse de k: %p\tContenu de k: %p\n", (void *) &k, (void *) k);
    	printf("L'adresse de i: %p\tContenu de i: %d\n", (void *) &i, i);
    }
     
    int main(void)
    {
    	comprendre_mem();
     
    	return EXIT_SUCCESS;
    }
    Voici ce que donne la sortie console:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    L'adresse de k: 0xbfceae60	Contenu de k: 0xbfceae64
    L'adresse de i: 0xbfceae64	 Contenu de i: 59
    Et voici l'assembleur généré pour la fonction comprendre_mem():
    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
    comprendre_mem:
            pushl   %ebp
            movl    %esp, %ebp
            subl    $40, %esp
            # La valeur 59 est stockée sur la pile dans la valiable i
            movl    $59, -4(%ebp)
            # L'adresse de i est calculée et sa valeur est plcée dans EAX
            leal    -4(%ebp), %eax
            # L'adresse de i est copiée dans sur la pile dans k
            movl    %eax, -8(%ebp)
            # Toute la suite concerne printf()
            movl    -8(%ebp), %eax
            movl    %eax, 8(%esp)
            leal    -8(%ebp), %eax
            movl    %eax, 4(%esp)
            movl    $.LC0, (%esp)
            call    printf
            movl    -4(%ebp), %eax
            movl    %eax, 8(%esp)
            leal    -4(%ebp), %eax
            movl    %eax, 4(%esp)
            movl    $.LC1, (%esp)
            call    printf
            leave
            ret
    Il n'y a absolument aucune magie nulle part! k est une variable située sur la pile qui contient une valeur qui correspond à l'adresse de i. L'emplacement mémoire de i est ici situé 4 "cases plus haut" que k. Ainsi, à l'adresse de k (0xbfceae60), on trouve bien la valeur 0xbfceae64 qui correspond à l'adresse de la variable i située 4 octets plus "haut".

    Thierry

    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++

    +

Discussions similaires

  1. Réponses: 1
    Dernier message: 14/03/2006, 09h13
  2. [PORT COM] RS485 et pointeur null...
    Par floanne dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 20/02/2006, 11h00
  3. get => pointeur null apres fermeture d'une sous-fenetre
    Par gorgonite dans le forum AWT/Swing
    Réponses: 15
    Dernier message: 11/02/2006, 21h42
  4. [Info][Mémoire] utilisée pour un pointeur null
    Par thomas_strass dans le forum Langage
    Réponses: 14
    Dernier message: 04/11/2004, 12h48
  5. Réponses: 4
    Dernier message: 06/04/2004, 21h57

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