Partage
  • Partager sur Facebook
  • Partager sur Twitter

Adresse d'une variable char

Retour de programme innatendu

    10 août 2023 à 13:03:34

    Bonjour, 

    J'étais en train d'étudier le fonctionnement d'un CPU 8 bits de l'époque (le Z80 de l'AMSTRAD CPC 6128, ma toute première machine et donc forcément ma préférée :p). Ce processeur avait 16 broches pour les adresses et 8 broches pour la data. 

    Du coup je me suis demandé: sur nos ordinateurs "modernes", combien de bits de data sont disponibles à chacune des adresses de la RAM?

    Pour ce faire, je me suis dit: un char est codé sur 8 bits. Donc je vais créer un tableau de char et j'afficherai les adresses successives des char de mon tableau. Si pour chaque char, l'adresse est incrémentée de 1, ça voudra dire qu'il y a bien 8 bits de donnée (1 octet) à chacune des adresses de ma RAM.

    Voici mon programme:

    #include <iostream>
    
    int main(){
    
    	char tableau[3] = {'a','b','c'};
    
    	for(int i=0;i<3;i++){
    		std::cout << "adresse tableau[" << i << "]: " << &(tableau[i]) << std::endl;
    	}
    	return 0;
    }

    mais à ma grande surprise voici ce que m'a renvoyé le programme:

    adresse tableau[0]: abc

    adresse tableau[1]: bc

    adresse tableau[2]: c

    ma question est la suivante: pourquoi renvoit-il les valeurs du tableau et non pas les adresses?

    PS:
    J'ai quand même eu la réponse à ma question en refaisant l'exercice avec des int (codés sur 4 octets), et le programme m'a renvoyé ce que j'attendais:
    adresse tableauInt[0]: 0x7ffe2bbd030c
    adresse tableauInt[1]: 0x7ffe2bbd0310
    adresse tableauInt[2]: 0x7ffe2bbd0314
    Merci beaucoup par avance pour le temps que vous aurez pris à me répondre et excellente journée à vous!
    Matthieu
    • Partager sur Facebook
    • Partager sur Twitter
      10 août 2023 à 14:31:31

      std::cout << "adresse tableau[" << i << "]: " << &(tableau[i]) << std::endl;

      N'affiche pas l'adresse mais la chaîne de caractère qui commence à cette adresse.

      Pour afficher l'adresse il faut caster en pointeur void :

      std::cout << "adresse tableau[" << i << "]: " << static_cast<void*>(&tableau[i]) << std::endl;


      Edit : La plus part du temps, les char sont codés sur 8 bits.

      -
      Edité par rouIoude 10 août 2023 à 14:33:12

      • Partager sur Facebook
      • Partager sur Twitter
      ...
        10 août 2023 à 14:43:06

        La définition choisie en C, et héritée en C++, c'est qu'un char fait exactement un byte. C'est l'unité de base. Que le char ait 7, 8, 16, ou 32 bits ne change rien au fait qu'un char fasse 1 byte. C'est accessible via la macro NCHAR_BITS.

        Et du coup, augmenter de 1 une adresse ne garantit pas d'augmenter d'un octet. Cela garantit d'augmenter d'un byte. Et donc de NCHAR_BITS.

        • Partager sur Facebook
        • Partager sur Twitter
        C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
          10 août 2023 à 15:33:38

          lmghs a écrit:

          C'est accessible via la macro NCHAR_BITS.

          C'est pas plutôt : CHAR_BIT ?

          • Partager sur Facebook
          • Partager sur Twitter
          ...
            11 août 2023 à 3:07:57

            Si. Merci. C'est fort possible. C'est dire à quel point je m'en sers souvent ^^'

            • Partager sur Facebook
            • Partager sur Twitter
            C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
              11 août 2023 à 18:51:32

              Je ne comprend pas ton raisonnement.

              Le fait qu'on microprocesseur soit 8, 16, 32 ou 64 bits, n'implique pas que les adresses successives soient espacées de 8, 16, 32 ou 64 bits.
              C'est la taille de la données qui compte, et non la taille de l'adresse.

              Surtout que, avec le cas particulier des tableaux, le microprocesseur va "ranger" les données dans des espaces memoire contigus, histoire de gérer cette dernière au mieux.
              Ainsi, un tableau de 5 caractères (type de données char, 8 bits), prendra 40 bits (ou 5 octets), avec par exemple, des adresses de valeur:
              0x7ffe2bbd0310
              0x7ffe2bbd0311
              0x7ffe2bbd0312
              0x7ffe2bbd0313
              0x7ffe2bbd0314
              (1 octet entre chaque adresse).

              Un tableau de 5 entiers (type de données int, 16 bits), prendra 80 bits (ou 10 octets), avec (toujours par exemple) des adresses de valeur:
              0x7ffe2bbd0310
              0x7ffe2bbd0312
              0x7ffe2bbd0314
              0x7ffe2bbd0316
              0x7ffe2bbd0318
              (2 octets entre chaque adresse).

              A ma connaissance, le nombre de bits d'un microprocesseur, influe d'abord sur le nombre de données adressables.
              Eventuellement sur la taille de certaines données (et dans ce cas, il faut consulter la norme).

              • Partager sur Facebook
              • Partager sur Twitter
                14 août 2023 à 9:20:24

                Pour en revenir à la question, c'est pas par C/C++ qu'il faut passer, mais par la lecture des informations techniques du processeur (datasheet) et des circuits associés. 

                Bon courage.

                • Partager sur Facebook
                • Partager sur Twitter
                  22 septembre 2023 à 15:20:25

                  Bonjour,

                  Je rebondis sur le sujet, car je pense que l'auteur a fait une erreur : tu ne devrais pas obtenir des adresses espacées de 4.

                  Comme tu le vois sur le screenshot, j'obtiens des adresses espacées de 1 (et non de 4) pour tableau de char. 

                  Car même si nos processeur sont actuellement de 64 bits (8 octets) , un tableau de char ne gaspille par 7 octets entre chaque char d'un tableau.

                  L'erreur vient tout d'abord du std::cout, si tu considères   &(tableau[i]) alors tu sors en char*  (donc en pointeur, ce que tu souhaites), MAIS, comment std::cout considère les char* ?  Comme une chaine ! Et donc il t'affichera une chaine.

                  Ici, je cast en void* pour que std::cout me sorte un pointeur, et on voit les adresses séparées de 1.

                  J'aimerais bien voir quel code t'a mené à un décalage de 4.

                  L'Amstrad est un bon souvenir pour moi :)

                  Si tu veux savoir la largeur de l'adressage, ce n'est pas comme ça que pourras l'avoir mais en demandant sizeof(void*), la largeur d'un pointeur te montreras la largeur d'adressage possible.

                  Avant les pross étaient de 32 bits, et les machines étaient bridées à 4 Go de RAM, parce qu'avec 32 bits, tu ne peux adresser que 4 Go

                  Maintenant, avec nos pross 64 bits, aucun soucis, on peut aller très loin.

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                  Adresse d'une variable char

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown