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 :

Problème avec malloc


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 74
    Par défaut Problème avec malloc
    Bonjour,

    Je ne parviens pas à allouer un tableau de manière dynamique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(int argc, char *argv[])
    {
    char *tab = NULL;
     
    tab = malloc(5 * sizeof(char));
    printf("%d\n", sizeof(tab));
    free(tab);
     
    return 0;
    }
    le sizeof me renvoie toujours une taille de 4 octets et je ne comprends pas pourquoi. Je compile sous gnu gcc.

    Merci de votre aide.

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 450
    Par défaut
    Bonjour,

    « sizeof » est un mot-clé réservé du C et pas une fonction dans le sens où on l'entend d'habitude. Ça veut dire aussi que sizeof est évalué à la compilation.

    Ici, tu écris sizeof(tab), donc il va toujours te renvoyer la taille du pointeur, quoi que celui pointe, soit quatre octets sur une machine 32 bits.

  3. #3
    Membre Expert
    Avatar de supersnail
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 719
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 719
    Par défaut
    Bonjour,

    C'est parce que sizeof te retourne la taille de ton pointeur vers la zone mémoire allouée... Or un pointeur a une taille de 4 octets (pour contenir une adresse de 32 bits).

    Donc tu as bien un tableau de 5 caractères qui est créé, mais tu ne peux malheureusement pas connaître sa taille (à part faire confiance à malloc qui renvoie 0 si la zone n'a pas pu être allouée).

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 74
    Par défaut
    Dans ce cas pour quoi quand on fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char tab[6] = "salut";
    printf("%d\n", sizeof(tab));
    celui-ci nous renvoie bien 6 ? Car tab est bien un pointeur sur le 1er élèment donc je devrai avoir 4 octets pour le pointeur.

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 450
    Par défaut
    Citation Envoyé par Flynet Voir le message
    Dans ce cas pour quoi quand on fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char tab[6] = "salut";
    printf("%d\n", sizeof(tab));
    celui-ci nous renvoie bien 6 ? Car tab est bien un pointeur sur le 1er élèment donc je devrai avoir 4 octets pour le pointeur.
    Eh non ! :-) tab est un tableau, mais invoquer tab seul renvoie l'adresse de ce tableau, donc une valeur de type « char * ». Par contre, si tu écris :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    const char * tab = "Salut';

    Là, tu te retrouves avec un sizeof(tab) égal à 4.

    C'est facile à retenir car, dans le cas de tab[6], tu alloues 6 caractères, mais tu n'alloues pas de mémoire supplémentaire pour stocker l'adresse du tableau (connue). Donc, à aucun moment, sizeof() ne pourrait te renvoyer 4.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 74
    Par défaut
    Donc si je comprends bien, le fait d'utiliser la déclaration sous forme de pointeur fait que sizeof renverra la taille du pointeur. Mais dans le cas du tableau, l'adresse de la mémoire étant connue, sizeof ne renverra que la taille du tableau ?

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 450
    Par défaut
    Citation Envoyé par Flynet Voir le message
    Donc si je comprends bien, le fait d'utiliser la déclaration sous forme de pointeur fait que sizeof renverra la taille du pointeur. Mais dans le cas du tableau, l'adresse de la mémoire étant connue, sizeof ne renverra que la taille du tableau ?
    C'est surtout que sizeof() va naturellement te renvoyer la taille qu'occupe une entité en mémoire. Lorsque tu déclares un pointeur, tu réserves quatre octets dans la pile. Lorsque tu déclares un tableau de six caractères, tu réserves exactement six octets dans la pile et rien d'autre (en considérant que chaque caractère occupe un seul octet et en négligeant les histoires de padding).

    Un tableau n'est pas accompagné d'un pointeur en mémoire qui contient l'adresse des données qu'il contient. Sinon, ça veut dire que tu pourrais changer cette valeur. Essaie par exemple de compiler ceci :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main (void)
    {
        char * pointer     = "Hello";
        char   buffer  [6] = "World";
     
        pointer = (char  *)0x12345678;
        buffer  = (char[6])0x12345678;
     
        return 0;
    }

    Code Shell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ gcc programme.c -o programme
    programme.c: In function ‘main’:
    programme.c:7: erreur: le transtypage spécifie un type de tableau

    Tu peux réaffecter « pointer » mais pas « buffer » car il n'y a pas de pointeur en mémoire associé au tableau.

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 814
    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 814
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Flynet Voir le message
    Dans ce cas pour quoi quand on fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char tab[6] = "salut";
    printf("%d\n", sizeof(tab));
    celui-ci nous renvoie bien 6 ? Car tab est bien un pointeur sur le 1er élèment donc je devrai avoir 4 octets pour le pointeur.
    Bien que les pointeurs et les tableaux soient souvent très similaires dans leur manipulation, un pointeur n'est pas un tableau et un tableau n'est pas un pointeur. Donc sizeof(tab) te donnera 6.

    La cause de la confusion vient dans le fait que bien souvent on utilise un pointeur pour manipuler le contenu d'un tableau. D'où l'idée que c'est la même chose.
    Exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char tab[6] = "salut";
    char *pt=tab;
    for (i=0; i < 6; i++)
        printf("i=%d => tab=(%p) %c et pt=(%p) %c\n", i, &tab[i], tab[i], &pt[i], pt[i])
    Mais la différence se voit ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char tab[6] = "salut";
    char *pt=tab;
    printf("taille tab: %d\n", sizeof(tab));
    printf("taille pt: %d\n", sizeof(pt));
    Et cette différence devient un gouffre quand on commence à travailler avec des tableaux multi-dimensionnels...
    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]

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 74
    Par défaut
    Merci de vos réponses, je comprend mieux à présent. Le problème c'est que sur le site où j'ai suivi la programmation, on nous fait comprendre que tableau est un pointeur et qu'il pointe sur le premier élèment du tableau d'où la confusion.

    Ma question maintenant porte plutôt sur ton code obsidian, j'ai bien compris qu'on essayait de réaffecter des adresses mémoires mais que signifient les :
    (char *)
    (char[6])

    C'est la première fois que je vois ce genre de choses.

  10. #10
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 450
    Par défaut
    Citation Envoyé par Flynet Voir le message
    Ma question maintenant porte plutôt sur ton code obsidian, j'ai bien compris qu'on essayait de réaffecter des adresses mémoires mais que signifient les :
    (char *)
    (char[6])
    Il est sage de choisir tout de suite un document complet et bien construit (par exemple, le K&R), ou les cours de C, sinon tu vas aller d'approximations en approximations, tu vas prendre de mauvaises habitudes, et ce sera difficile de les changer ensuite.

    Un nom de type seul entre parenthèses précédant une expression, c'est un « cast » ou « transtypage » en français. Il s'agit de convertir la valeur concernée dans le type en question. C'est aussi répandu en C que les pointeurs et fait partie des fondamentaux du langage.

    Par exemple, « (int)2.5 » vaut « 2 », puisque « 2.5 » est de type double par défaut, puis converti en int par le biais du cast. Ne subsiste donc que la partie entière.

    Souvent, ces conversions sont implicites quand le compilateur sait les faire (conversions entre types numériques), la plupart du temps, elles sont explicites, et parfois, elles sont impossibles.

    En particulier, les pointeurs sont des types à part entière et peuvent donc être transtypés. C'est très utile mais c'est aussi la porte ouverte à tous les bricolages, même les plus sales. Tu ne peux pas convertir un entier en structure, par exemple, parce que ça n'a pas de sens et, de toutes façons, le compilo ne saurait pas quel genre de résultat ce serait censé donner. Par contre, une adresse mémoire étant une adresse mémoire, tu peux très bien affirmer qu'un « int * », soit « l'adresse en mémoire d'un int » est en fait l'adresse en mémoire de n'importe quoi d'autre. À partir du moment où c'est faisable (l'adresse en elle-même reste inchangée) et que tu affirmes cela explicitement au compilo, il va te croire.

    Dans le cas qui nous intéresse, donc, j'invente une adresse bidon (« 0x12345678 ») qui est, à ce stade, considérée par le compilateur comme un nombre entier et pas un pointeur. Ensuite, je transtype ce nombre vers le type de chacune de mes variables, pour avoir des arguments de même nature de chaque côté du « = ».

    On voit alors qu'on peut affecter une nouvelle valeur à un pointeur, mais pas à un tableau.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 74
    Par défaut
    Pour quoi ne pas avoir directement fait :
    Car de toute manière l'adresse est elle aussi un nombre. De la même manière on ne fait pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int nombre = 0;
    nombre = (int)56;
    A moins que dans le 1er cas, le compilateur ne sait pas faire cette conversion implicite ?

  12. #12
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 450
    Par défaut
    Citation Envoyé par Flynet Voir le message
    Pour quoi ne pas avoir directement fait :
    Car de toute manière l'adresse est elle aussi un nombre.
    Mais pas d'un point de vue sémantique. Pour le C, un nombre est un nombre, avec ses propriétés, et un pointeur est un pointeur, avec ses autres propriétés. Par exemple, il n'est pas possible d'additionner deux pointeurs. Additionner deux adresses en mémoire ne correspond pas à une troisième adresse en mémoire.

    Exemple : 5 + 8 = 13. Ces deux expressions (de part et d'autre de « = ») représentent la même valeur du même type. Tu peux donc sans problème substituer l'une à l'autre. Par contre, ce n'est pas parce que dans ta rue, tu habites au № 5 et qu'un de tes amis habite au № 8 qu'à vous deux, vous habitez au № 13.

    Donc, le C est capable de convertir directement les types numériques entre eux (int, long, float, etc) parce qu'ils font tous partie de ℝ ou de l'un de ses sous-ensembles.

    De plus, le plan mémoire d'une machine n'est pas forcément continu, et certaines valeurs peuvent être interdites directement au niveau du micro-processeur :

    http://www.developpez.net/forums/d61...r/#post3615287

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int nombre = 0;
    nombre = (int)56;
    Oui, mais justement : si l'on enlève le cast, de quel type est « 56 » ? Cette question n'est pas anodine et la réponse est apportée dans la norme de façon explicite. Cela permet d'expliquer aussi certains petits mystères tels que celui qui se produit dans ce petit morceau de code :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <stdio.h>
     
    int main (void)
    {
        long long x;
     
        x = 0x40000000;
        x = x << 2;
        printf ("x vaut %llx\n",x);
     
        x = 0x40000000 << 2;
        printf ("x vaut %llx\n",x);
     
        return 0;
    }

    … qui donne :

    Code Shell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ ./programme
    x vaut 100000000
    x vaut 0

    Je te laisse deviner pourquoi.

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 74
    Par défaut
    Euh, étrangement j'ai pas le même résultat

    Je l'ai compilé sous gcc mais voilà ce que j'obtiens :
    x vaut 0
    x vaut 0

    ps: Quelles sont les balises à mettre pour le shell ?

  14. #14
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 450
    Par défaut
    C'est ma faute. Il fallait utiliser « long long » à la place de « long », et « %llx » plutôt que « %lx », et compiler en C99. L'exemple est censé fonctionner partout. S'il fonctionnait quand même chez moi, c'est justement parce que j'utilise une machine 64 bits.

    En soi, c'est déjà un effet de bord intéressant à étudier.

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 74
    Par défaut
    Pour le premier cas je crois comprendre qu'il y a une conversion implicite, ce qui ne doit pas être le cas du 2e. Néanmoins certaines questions me viennent à l'esprit.

    La première c'est qu'en modifiant un peu le code gcc m'a fait comprendre que l'argument x passé à printf est de type long long int or on l'a déclaré comme un long long ?

    Ensuite j'ai essayé de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf ("x vaut %llx\n", (0x40000000 << 2));
    et gcc me dit que l'argument est un int, donc je me demande pourquoi on a déclaré un long long pour le stocker ? Sinon, je retourne toujours sur le même résultat 0 en utilisant "%d".

    Enfin pourquoi est-ce que le 2e cas ne marche pas ? Et pourquoi quand je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf ("x vaut %d\n", (0x30000000 << 2));
    J'obtients bien un résultat : -1073741824
    Est-ce lié au fait que (0x40000000 << 2) dépasse la capacité d'un int ?

  16. #16
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 450
    Par défaut
    Citation Envoyé par Flynet Voir le message
    et gcc me dit que l'argument est un int, donc je me demande pourquoi on a déclaré un long long pour le stocker ?
    Tu chauffes ! :-)

    Est-ce lié au fait que (0x40000000 << 2) dépasse la capacité d'un int ?
    Oui.

  17. #17
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 814
    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 814
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Flynet Voir le message
    Et pourquoi quand je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf ("x vaut %d\n", (0x30000000 << 2));
    J'obtients bien un résultat : -1073741824
    Est-ce lié au fait que (0x40000000 << 2) dépasse la capacité d'un int ?
    En fait, le processeur ne s'embête pas. Il fait le calcul et positionne le résultat là où tu l'as demandé. Et si le résultat est trop grand pour tenir, ben ce qui dépasse disparait.

    Cette méthode permet d'ailleurs des raccourcis de calculs.
    Exemple: regardons le codage binaire de +3 et de -3 sur 8 bits
    +3 = 0000 0011
    -3 = 1111 1101 (chaque bit de +3 est inversé puis on ajoute 1 au résultat)

    Calculons maintenant (+3) + (-3) toujours sur 8 bits
    0000 0011
    + 1111 1101
    ------------
    1 0000 0000
    Tu remarques que le premier "1" dépasse la capacité de stockage => il est supprimé et le résultat donne 0 ce qui est mathématiquement correct.
    Ainsi, la méthode de codage des négatifs (inverser chaque bit du positif puis ajouter 1) permet au processeur de calculer plus rapidement.

    Regardons maintenant 0x30000000. Cela donne
    00110000 00000000 00000000 00000000

    Décalé de 2, cela donne 11000000 00000000 00000000 00000000
    Le premier "1" indiquant un négatif, pour calculer de quel nombre il s'agit je le convertis en positif selon la méthode inverse (enlever 1 puis tout inverser)
    Enlever 1 donne alors 10111111 11111111 11111111 11111111
    Tout inverser donne ensuite 01000000 00000000 00000000 00000000 soit 0x40000000 soit 1073741824

    Conclusion: 0x30000000 << 2 donne bien -1073741824...
    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]

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 74
    Par défaut
    Bonjour,

    Oui en fait j'avais trouvé la réponse mais je n'ai pas eu le temps de poster.
    Merci quand même pour ton explication Sve@r.

    En fait des deux cotés de "<<", 0x40000000 et 2 sont tous les deux des int. Du coup le compilateur ne fait rien et quand on déplace de 2 bits on arrive à 32 bits qui est supérieur a la capacité d'un int d'où le résultat 0. Comme tu l'as expliqué le '1' a été expulsé.

    En faisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x = (long long) 0x40000000 << 2;
    le 0x40000000 est transformé en long long de même que le 2 de manière implicite. Du coup le résultat est bien stocké.

  19. #19
    Membre actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations forums :
    Inscription : Février 2010
    Messages : 87
    Par défaut
    Citation Envoyé par Flynet Voir le message
    On nous fait comprendre que tableau est un pointeur et qu'il pointe sur le premier élèment du tableau d'où la confusion.
    oui c'est vrais que un tableau c'est un pointeur qui pointe sur le premier élément et pour les variables aussi et pour un pointeur normale en réalité c'est un pointeur de pointeur je vais t'exprimer ça pas a pas, un pointeur tous simplement une adresse sauvé en mémoire, je vais te donne une exemple imaginer que nous savons l'adresse de pointeur avant de le crée
    #define pointeur 0x956000

    unsigned char data = 0xAA;
    pointeur = data ; //ici on a affecté la donnée 0xAA a l'adresse 0x95600
    c'est la meme chose avec la déclaration de pointeur mais ici on a une adresse de pointeur valide definé par le system
    unsigned char *pointeur = NULL;

    unsigned char data = 0xAA;
    pointeur = data ; //ici on a affecté la donnée 0xAA a une l'adresse valide
    et pour les tableaux, un 'nom' de tableau lui meme est un variable imagine toi exemple on déclare un tableau de dix cases et on laisse les crochets"[9]" a coté voir ce qu'il reste
    unsigned char nomdetableau;//déclaration de tablau de dix cases
    il nous reste qu'une variable / mais que fait cette variable ici?/pour sauvé une adresse /la qu'elle? /c'est le system qui va choisir cette adresse/ pour quoi?/pour mettre les dix cases de ton tableau en mémoire/c'est la meme chose avec un pointeur normale avec seulement un nom différant
    unsigned char pointeur[9]; //un pointeur de dix cases
    meme chose avec les variables et bonne chanse

  20. #20
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 814
    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 814
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par PIC16F877A Voir le message
    oui c'est vrais que un tableau c'est un pointeur
    non

    Citation Envoyé par PIC16F877A Voir le message
    qui pointe sur le premier élément
    Le nom d'un tableau est équivalent à l'adresse de son premier élément

    Citation Envoyé par PIC16F877A Voir le message
    et pour les variables aussi et pour un pointeur normale en réalité c'est un pointeur de pointeur
    Hum, es-tu certain que les mots vont bien de ton cerveau au clavier sans altération intermédiaire due à un facteur externe indépendant de ta volonté ???

    Citation Envoyé par PIC16F877A Voir le message
    je vais t'exprimer ça pas a pas, un pointeur tous simplement une adresse sauvé en mémoire, je vais te donne une exemple imaginer que nous savons l'adresse de pointeur avant de le crée
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #define pointeur 0x956000
     
    unsigned char data = 0xAA;
    pointeur = data ; //ici on a affecté la donnée 0xAA a l'adresse 0x95600
    Superbe !!! Dans ton exemple, pointeur n'est pas une variable mais une macro. Tu ne peux pas lui mettre de valeur !!!

    Citation Envoyé par PIC16F877A Voir le message
    c'est la meme chose avec la déclaration de pointeur mais ici on a une adresse de pointeur valide definé par le system
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    unsigned char *pointeur = NULL;
     
    unsigned char data = 0xAA;
    pointeur = data ; //ici on a affecté la donnée 0xAA a une l'adresse valide
    Magnifique. Tu stockes un caractère dans une zone prévue pour recevoir une adresse !!!

    Citation Envoyé par PIC16F877A Voir le message
    et pour les tableaux, un 'nom' de tableau lui meme est un variable imagine toi exemple on déclare un tableau de dix cases et on laisse les crochets"[9]" a coté voir ce qu'il reste

    il nous reste qu'une variable / mais que fait cette variable ici?/pour sauvé une adresse /la qu'elle? /c'est le system qui va choisir cette adresse/ pour quoi?/pour mettre les dix cases de ton tableau en mémoire/c'est la meme chose avec un pointeur normale avec seulement un nom différant
    Et vice-versa

    Citation Envoyé par PIC16F877A Voir le message
    meme chose avec les variables et bonne chanse
    Oui, avec tes explications nébuleuses, il en aura effectivement super besoin de "chance" !!!


    Citation Envoyé par Flynet Voir le message
    En faisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x = (long long) 0x40000000 << 2;
    le 0x40000000 est transformé en long long de même que le 2 de manière implicite. Du coup le résultat est bien stocké.
    Oui. Tout calcul s'exécute dans le type le plus large des opérandes impliqués dans le calcul.

    Attention toutefois, car le type le plus large ne s'applique qu'aux opérandes en cours de calculs et non ceux qui attendent leur tour.

    Exemple: printf("%f", 3/2 + 1.0)

    Voyant dans ce calcul deux int et un float, tu peux supposer que le calcul se fera en float et que tu obtiendras 2.5
    Or la première opération "3/2" ne fait intervenir que des int et le "1.0" n'étant pas impliqué n'a aucune action. Le calcul se fera donc en int et donnera un int "1". Puis 1 + 1.0 se fera bien en float mais trop tard et donnera alors malheureusement 2.0
    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]

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. problème avec malloc
    Par cyril_sy dans le forum C
    Réponses: 13
    Dernier message: 12/05/2007, 13h49
  2. Problème avec malloc et autre
    Par ego dans le forum C
    Réponses: 5
    Dernier message: 02/05/2007, 18h29
  3. probléme avec malloc
    Par tomasi dans le forum C
    Réponses: 18
    Dernier message: 15/11/2006, 15h15
  4. Problème avec malloc
    Par f56bre dans le forum C
    Réponses: 11
    Dernier message: 13/11/2006, 14h36
  5. Problème avec malloc.
    Par kmitz dans le forum C
    Réponses: 2
    Dernier message: 25/03/2006, 18h05

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