#include<iostream>
using namespace std;
int main()
{
int *p,*c;
p=(int*)10;
c=(int*)20;
cout<<(int)p<<(int)c;
}
Somebody asked me "What is wrong with the above code?" and I couldn't figure it out. Someone please help me.
7 Réponses :
Le fait que les types de données De plus, Casting d'un I Essayez-moi EM> Essayez de compiler cela sous GCC et cela a fonctionné bien, mais c'est probablement plus par accident que de bon design. P> int code> et de pointeur ne soient pas nécessaires pour avoir le même nombre de bits, selon la norme C ++, est une chose - cela signifie que vous pourriez perdre de la précision. P>
int code> à un pointeur code> int code> Retour à nouveau est stupide. Pourquoi ne pas simplement le laisser comme un int code>? P>
Je pense que vous avez attiré l'intention de la question (qui est clairement une question d'une affaire d'une interview ou d'une personne), mais je suppose que le code présentera le comportement prévu sur n'importe quelle plate-forme où INT et INT * peut représenter les valeurs 10 et 20.
Dan est correct - le code, comme écrit, fonctionnera sur la plupart des plates-formes modernes. Mais utiliser des pointeurs pour stocker des nombres entiers provoquera généralement des accidents ou d'autres bugs si vous déréférez ces pointeurs. Vous voyez de temps en temps des gens qui savent vraiment ce qu'ils font du code d'écriture comme celui-ci, mais je considère que c'est une pratique douteuse qui devrait généralement être évitée. Comme on dit sur les mythbusters, "s'il vous plaît, n'essayez pas ceci à la maison!"
@Bob plus fréquemment, vous voyez des personnes qui ne savent vraiment pas ce qu'ils font de l'écriture de code comme celui-ci.
Ce n'est pas seulement "stupide" de lancer INT au pointeur et à l'arrière. Il est défini par la mise en œuvre, et probablement, tous les entiers convertis à un pointeur INT valide, donc sur certaines plates-formes, le code pourrait s'écraser même si les pointeurs ne sont jamais déréférencés.
@JAlf, définis par la mise en œuvre non une mauvaise chose à condition que vous sachiez que ce sont des limitations (et que vous n'êtes pas préoccupé par la portabilité massive). Comme je l'ai dit, GCC sous Ubuntu a bien fonctionné pour cela, bien que vous ayez vraiment besoin de vérifier le Doco pour que votre compilateur soit sûr (je n'ai pas). Mon point était, même si la mise en œuvre le permettait, c'est toujours une chose idiote à faire.
Vrai. Je voulais juste souligner que cela peut réellement échouer sur certains systèmes, ce qui serait souvent considéré plus que "stupide";)
Vous attribuez des valeurs (10 et 20) aux pointeurs qui constituent évidemment un problème potentiel si vous essayez de lire les données à ces adresses. Jeter le pointeur sur un entier est aussi vraiment moche. Et votre fonction principale n'a pas de déclaration de retour. C'est juste quelques choses. P>
Principal () n'a pas besoin d'une déclaration de retour. Le compilateur compatible des normes l'insère. www2.research.att.com/~bs/bs_faq2.html , Refeer à la question "Puis-je écrire" Void Main () "?.
Vous pouvez écrire "VOID Main ()" qui serait meilleur IMHO. Je sais que le compilateur ajoute la déclaration de retour, mais il est à peine une bonne pratique d'écrire du code avec un tas d'avertissements lors de la compilation et de tout ce qui ne va pas avec le code générerait des avertissements de compilateur afin que mon point soit mon point. Allumez tous les avertissements et vous verrez obtenir de l'aide au compilateur pour connaître «Qu'est-ce qui ne va pas avec le code».
En supposant que j'ai raison sur ce que cela est censé être, il devrait ressembler à ceci: afin d'assigner ou de récupérer une valeur à une variable référencée par un pointeur, vous Besoin de Déréférence IT. p> Qu'est-ce que votre code fait est de lancer 10 dans le pointeur sur INT (qui est l'adresse de la mémoire où réside l'INT). P> P>
Cela va segfault sur la plupart des implémentations.
@Adam, je vais vous donner l'avantage du doute et supposez que vous vouliez dire "C'est ce que votre code problème i> doit ressembler à" plutôt que "ce code est la solution à votre problème". Étant donné que P et C sont ininitialisés, ils pourraient être définis sur n'importe quoi i> ce qui est un comportement indéfini.
Désolé, j'ai oublié de mettre ce bit. Corrigé.
Les adresses P et C peuvent être plus grandes que INT. P>
@FUPSDUCK: Les adresses P et C seront de taille que celle de l'INT. Tous les pointeurs sont 32 bits, identiques que la taille int.
@ GoldenMean, 64 bits Pointeurs et 32 bits IntS ne sont pas un rares de nos jours.
Il y a plus ou moins tout ce qui ne va pas avec celui-ci:
int *p,*c; p=(int*)10; c=(int*)20;
Cela n'a pas l'air très intentionnel. P>
Et je suppose que tout le programme va simplement planter. p> p>
Non, il ne changera pas, tant que vous n'essayez pas d'utiliser ces pointeurs vers référence i> adresses de mémoire 10 et 20.
@Bob: Cela pourrait se bloquer. C'est défini par la mise en œuvre. La CPU pourrait détecter que celles-ci sont des pointeurs non valides et un piège dès que les pointeurs sont créés.
Certains voulaient une citation de la norme C ++ (je l'aurais posé dans les commentaires de cette réponse si le format des commentaires n'était pas si restreint), voici deux à partir de la version 1999:
5.2.10 / 3 p>
Le mappage effectué par
réinterpret_cast code> est défini la mise en oeuvre. P> BlockQuote>5.2.10 / 5 P>
Une valeur du type de type ou d'énumération intégré peut être explicitement convertie en pointeur. Un pointeur converti en un entier de taille suffisante (si la fourmi existe sur la mise en œuvre) et retour au même type de pointeur aura sa valeur initiale; mappages entre les pointeurs et Les entiers sont définis par ailleurs de la mise en œuvre. P> BlockQuote>
Et je ne vois rien de mandater que ce cartographie défini par la mise en œuvre doit donner une représentation valide pour toutes les intrants. Autrement dit, une mise en œuvre sur une architecture avec des registres d'adresse peut très bien piéger lors de l'exécution p>
xxx pré> si le mappage ne donne pas une représentation valide à ce moment-là (oui, qu'est-ce que c'est un La représentation valide pour un pointeur peut compter de temps. Par exemple
Supprimer code> peut faire invalider la représentation du pointeur supprimé). P> P>
Suscité pour la deuxième citation. Les moules de style C et réinterpret_cast ont un comportement différent, donc je ne suis pas certain que la première citation s'applique.
Dan, toute la section 5.2.10 concerne Reterpret_cast, de sorte que les deux devis sont sur REINIERPRET_CAST. Mais en C ++, la syntaxe de CAST C est définie en termes d'autres moulages et, dans ce cas, c'est la définition de réinterpret_cast qui s'applique.
@Aprogrammer: Merci, je ne pouvais pas le trouver dans la norme C ++ :)
En pratique, les pointeurs ne seront probablement pas valides (en supposant que INT nécessite un alignement de 4 octets, au moins les 10 one ne seront pas correctement alignés) et bien sûr, les deux sont susceptibles de pointer vers une page de mémoire non mappée. Beaucoup d'opportunités pour le processeur de piéger.
@JAlf, il y a beaucoup d'occasions de piéger lorsque la déséroférience du pointeur des architectures communes; J'ignore particulièrement que la norme permet de piéger lors du chargement du pointeur sans la déséroférance (si vous utilisez le segment, vous pouvez obtenir ce piège sur un X86)
@Aprogrammer: Oui, c'est ce que je voulais dire aussi. Désolé si cela semblait être en désaccord. Je voulais juste fournir d'autres exemples de la raison pour laquelle une CPU pourrait piéger dès que le pointeur était chargé, même s'il n'est jamais déréférencé. +1 de moi
Le problème sur certaines plates-formes dont vous avez besoin voir la documentation de la glib sur type conversion de macros . P> et pour les personnes qui pourraient ne pas trouver une utilisation pour ce type d'expressions, il est possible de renvoyer des données Valeur du pointeur à l'intérieur des fonctions de retour. Vous pouvez trouver des exemples réels dans le monde, où il vaut mieux utiliser cet idiome, au lieu d'attribuer un nouvel entier sur le tas, et de le retourner - de mauvaise performance, de la fragmentation de la mémoire, juste laid. P> P> P> P> P> P> P> P> P> P> P> >
Avez-vous considéré cela comme la réponse valide: "rien". Un intervieweur est généralement intéressé par comment i> vous arrivez à une réponse, pas la réponse.
Un nom plus descriptif ne ferait pas mal.