web-dev-qa-db-fra.com

Pourquoi l'adresse des données de caractère n'est-elle pas affichée?

class Address {
      int i ;
      char b;
      string c;
      public:
           void showMap ( void ) ;
};

void Address :: showMap ( void ) {
            cout << "address of int    :" << &i << endl ;
            cout << "address of char   :" << &b << endl ;
            cout << "address of string :" << &c << endl ;
}

La sortie est:

         address of int    :  something
         address of char   :     // nothing, blank area, that is nothing displayed
         address of string :  something 

Pourquoi?

Une autre chose intéressante: si int, char, string est en public, alors la sortie est

  ... int    :  something 
  ... char   :   
  ... string :  something_2

something_2 - something est toujours égal à 8. Pourquoi? (pas 9)

44
user478571

Lorsque vous prenez l'adresse de b, vous obtenez char *. operator<< interprète cela en tant que chaîne C et essaie d'imprimer une séquence de caractères au lieu de son adresse.

essayez plutôt cout << "address of char :" << (void *) &b << endl.

[EDIT] Comme l'a commenté Tomek, une distribution plus appropriée à utiliser dans ce cas est static_cast, qui constitue une alternative plus sûre. Voici une version qui l'utilise à la place de la distribution de style C:

cout << "address of char   :" << static_cast<void *>(&b) << endl;
72
hrnt

Il y a 2 questions:

  • Pourquoi il n'imprime pas l'adresse du caractère:

Les pointeurs d’impression impriment l’adresse pour le int*et le string*, mais pas le contenu pour char* car il existe une surcharge particulière dans operator<<. Si vous voulez l'adresse alors utilisez: static_cast<const void *>(&c);

  • Pourquoi la différence d'adresse entre int et string est-elle 8

sizeof(int) est 4 sur votre plate-forme et sizeof(char) est 1. Vous devriez donc vraiment vous demander pourquoi 8 et non 5. La raison en est que la chaîne est alignée sur une limite de 4 octets. Les machines fonctionnent avec des mots plutôt que des octets et plus rapidement si les mots ne sont pas "divisés" en quelques octets ici et quelques octets ici. Ceci s'appelle alignement

Votre système est probablement aligné sur des limites de 4 octets. Si vous aviez un système 64 bits avec des entiers 64 bits, la différence serait de 16.

(Remarque: le système 64 bits fait généralement référence à la taille d'un pointeur et non d'un int. Ainsi, un système 64 bits avec un int de 4 octets aurait toujours une différence de 8, 4 = 1 = 5 mais arrondi à 8). Si sizeof (int) est 8 alors 8 + 1 = 9 mais ceci arrondit à 16)

23
CashCow

Lorsque vous transmettez en continu l'adresse d'un caractère à un ostream, il l'interprète comme étant l'adresse du premier caractère d'une chaîne ASCIIZ "style C" et tente d'imprimer la chaîne présumée. Vous n'avez pas de terminateur NUL, donc la sortie continuera d'essayer de lire de la mémoire jusqu'à ce qu'il en trouve un ou le système d'exploitation l'arrête pour avoir tenté de lire une adresse invalide. Toutes les ordures analysées seront envoyées à votre sortie.

Vous pouvez probablement le faire afficher l'adresse que vous voulez en le lançant, comme dans (void*)&b.

Concernant les décalages dans la structure: vous avez observé que la chaîne est placée au décalage 8. Ceci est probablement dû au fait que vous avez des ints de 32 bits, puis un caractère de 8 bits, puis le compilateur choisit d’insérer 3 caractères de plus de 8 bits L'objet de chaîne sera aligné sur une limite de mot de 32 bits. De nombreux processeurs/architectures de mémoire ont besoin de pointeurs, d'intes, etc. pour se situer sur des limites de taille Word afin d'effectuer des opérations efficaces sur eux. Sinon, ils devraient effectuer beaucoup plus d'opérations pour lire et combiner plusieurs valeurs en mémoire avant de pouvoir les utiliser. dans une opération. Selon votre système, il se peut que chaque objet de classe doive commencer par une limite de Word ou que std::string en particulier commence par un size_t, un pointeur ou un autre type nécessitant un tel alignement.

13
Tony Delroy

En effet, lorsque vous transmettez un char* à std::ostream, il affiche la chaîne de style C (c'est-à-dire: tableau de caractères, char*) vers lequel il pointe.

Rappelez-vous que "hello" est un char*.

10
peoro

L'adresse de char est traitée comme une chaîne terminée par zéro et affiche le contenu de cette adresse, qui est probablement non définie, mais dans ce cas une chaîne vide. Si vous lancez les pointeurs sur void *, vous obtiendrez les résultats souhaités.

La différence entre quelque chose 2 et 8 étant due à l'alignement et à la capacité du compilateur à décider lui-même où les variables sont déclarées dans la pile.

4
trojanfoe

Pour le deuxième problème - le compilateur par défaut complétera les membres de la structure. Le pad par défaut correspond à sizeof(int), 4 octets (sur la plupart des architectures). C'est pourquoi une int suivie d'une char prendra 8 octets dans la structure, donc le membre string est à l'offset 8.

Pour désactiver le remplissage, utilisez #pragma pack(x), où x est la taille du pad en octets.

2
Eli Iser

Votre syntaxe devrait être 

cout << (void*) &b
2
Taranfx

hrnt a raison sur la raison du blanc: &b est de type char* et est donc imprimé sous forme de chaîne jusqu'au premier octet nul. Vraisemblablement, b est égal à 0. Si vous définissez b sur, par exemple, 'A', vous devez alors vous attendre à ce que la sortie imprimée soit une chaîne commençant par 'A' et se poursuivant avec un déchet jusqu'au octet zéro suivant. Utilisez static_cast<void*>(&b) pour l’imprimer sous forme d’adresse.

Pour votre deuxième question, &c - &i est 8, car la taille d'un int est de 4, le caractère est de 1 et la chaîne commence à la limite de 8 octets suivante (vous êtes probablement sur un système 64 bits). Chaque type a un alignement particulier et C++ aligne les champs de la structure en fonction, en ajoutant le remplissage de manière appropriée. (La règle de base est qu'un champ primitif de taille N est aligné sur un multiple de N.) En particulier, vous pouvez ajouter 3 autres champs char après b sans affecter l'adresse &c.

0
DS.