Pourquoi la sortie est-elle vide? les pointeurs sont capables de modifier mais ne peuvent pas lire.pourquoi?
[Desktop]ð g++ test_pointer.cpp [Desktop]ð ./a.out @ @ 16843009
#include <iostream>
using namespace std;
int main(){
int a = 0;
char *x1,*x2,*x3,*x4;
x1 = (char *)&a;
x2 = x1;x2++;
x3 = x2;x3++;
x4 = x3;x4++;
*x1=1;
*x2=1;
*x3=1;
*x4=1;
cout <<"@" << *x1 << " " << *x2 << " " << *x3 << " " << *x4 << "@"<<endl ;
cout << a << endl;
}
Je veux lire la valeur d'un entier en utilisant des pointeurs de type char. donc je peux lire octet par octet.
5 Réponses :
Vous diffusez des char s. Ceux-ci sont automatiquement ASCII-ised pour vous par IOStreams *, donc vous voyez (ou plutôt, ne voyez pas) caractères non imprimables (en fait, tous les octets 0x01).
Vous pouvez convertir en int pour voir la valeur numérique, et peut-être ajouter std :: hex code > pour une vue conventionnelle.
Exemple:
#include <iostream>
#include <iomanip>
int main()
{
int a = 0;
// Alias the first four bytes of `a` using `char*`
char* x1 = (char*)&a;
char* x2 = x1 + 1;
char* x3 = x1 + 2;
char* x4 = x1 + 3;
*x1 = 1;
*x2 = 1;
*x3 = 1;
*x4 = 1;
std::cout << std::hex << std::setfill('0');
std::cout << '@' << std::setw(2) << "0x" << (int)*x1
<< ' ' << std::setw(2) << "0x" << (int)*x2
<< ' ' << std::setw(2) << "0x" << (int)*x3
<< ' ' << std::setw(2) << "0x" << (int)*x4
<< '@' << '\n';
std::cout << "0x" << a << '\n';
}
// Output:
// @0x01 0x01 0x01 0x01@
// 0x1010101
Ceux qui disent que votre programme n'est pas défini sont incorrects (en supposant que votre int contient au moins quatre octets ); l'aliasing des objets via char * est spécifiquement autorisé.
La sortie 16843009 est correcte; c'est égal à 0x01010101 que vous verriez à nouveau si vous mettez votre flux en mode hexadécimal.
N.B. Certaines personnes recommanderont reinterpret_cast et static_cast , au lieu des casts de style C, bien que personnellement je les trouve moche et inutile dans ce cas particulier. Pour la sortie, vous pouvez au moins écrire + * x1 pour obtenir une promotion "gratuite" vers int (via l'opérateur unaire + ), mais ce n'est pas très auto-documenté.
* Techniquement, c'est quelque chose comme le contraire; IOStreams convertit généralement automatiquement vos nombres, vos valeurs booléennes et vos objets dans les bons caractères ASCII pour qu'ils apparaissent correctement à l'écran. Pour char , il ignore cette étape, en supposant que vous fournissez déjà la valeur ASCII souhaitée.
Si j'ai bien compris votre problème, voici la solution
#include <stdio.h>
#include <iostream>
using namespace std;
int main(){
int a = 0;
char *x1,*x2,*x3,*x4;
x1 = (char*)&a;
x2 = x1;x2++;
x3 = x2;x3++;
x4 = x3;x4++;
*x1=1;
*x2=1;
*x3=1;
*x4=1;
cout <<"@" << (int)*x1 << " " << (int)*x2 << " " << (int)*x3 << " " << (int)*x4 << "@"<<endl ;
cout << a << endl;
}
Super, alors vous devriez marquer la réponse qui vous a aidé afin que les gens sachent qu'elle a été répondue.
Vous devez toujours expliquer la solution que vous proposez et comment elle résout le problème déclaré. Ne vous contentez pas de vider le code. Ne mendiez pas non plus pour que la réponse accepte; cela ne fait que 20 minutes que la question a été publiée.
et veuillez ne pas utiliser de casts de style C et .
TBH Je suis d'accord avec les casts de style C pour des choses comme ça cos reinterpret_cast est moche AF mais oui
@LightnessRacesinOrbit cos reinterpret_cast est moche - Lors du casting du pointeur, cela ne fait aucune différence, mais je voulais dire les casts dans les appels à l'opérateur < <() où un static_cast <> () suffirait.
@Swordfish Peut-être. J'ai ajouté un petit détail à ma réponse à ce sujet il y a quelques minutes
@LightnessRacesinOrbit Vous avez mal compris mon intention, je ne voulais pas qu'il marque ma propre réponse comme acceptée. Je voulais dire qu'il devrait marquer la réponse qui l'a aidé. De plus, j'ai trouvé cette question en utilisant le filtre c dans le débordement de pile, c'est pourquoi j'ai utilisé des moulages de style C
La question (et votre réponse) sont clairement C ++, malgré la balise bum;)
@LightnessRacesinOrbit Je suis tellement noob que je ne savais même pas, j'ai juste jeté le code dans mon IDE en ligne, ajouté des castings, et cela a fonctionné.
Jetez un œil à vos déclarations des x
cout <<"@" << int(*x1) << " " << int(*x2) << " " << int(*x3) << " " << int(*x4) << "@"<<endl ;
ce sont des pointeurs vers des caractères (caractères). p>
Dans votre sortie de flux, ils sont interprétés comme des caractères imprimables. Un bref aperçu de la ascii-Table vous permet de voir que les nombres inférieurs ne sont pas imprimables.
Puisque votre int a est égal à zéro, les x qui pointent vers les octets individuels sont égaux à zéro.
Une possibilité d'obtenir une sortie lisible serait de transtyper les caractères en int , de sorte que le flux imprime la représentation numérique à la place du caractère ascii:
char *x1,*x2,*x3,*x4;
En supposant qu'un int fait au moins 4 octets de long sur votre système, le programme manipule les 4 octets de int a .
Le résultat 16843009 est la valeur décimale de 0x01010101 , donc c'est comme vous pouvez vous y attendre.
Vous ne voyez rien dans la première ligne de sortie car vous écrivez 4 caractères de une valeur binaire 1 (ou 0x01 ) qui sont des caractères invisibles (ASCII SOH).
Lorsque vous modifiez votre programme comme ceci
XXX
vous verrez la sortie avec les caractères attendus
@1 3 5 7@ 926233393
La valeur 926233393 est la représentation décimale de 0x37353331 où 0x37 est la valeur ASCII du caractère '7' etc.
(Ces résultats sont valides pour un peu- architecture endienne.)
Vous pouvez utiliser unaire + pour convertir le type de caractère (imprimé sous forme de symbole) en type entier (imprimé sous forme de nombre):
cout <<"@" << +*x1 << " " << +*x2 << " " << +*x3 << " " << +*x4 << "@"<<endl ;
Voir promotion intégrale :
vous avez un comportement indéfini. vous ne pouvez pas pointer quelque part, augmenter et espérer ensuite obtenir quelque chose de significatif. L'arithmétique des pointeurs n'est bien définie qu'à l'intérieur des tableaux
quelle sortie voulez-vous générer? Je suis sûr que si vous clarifiez cela, il peut y avoir une solution valable (je doute même que vous ayez besoin de pointeurs)
Je ne suis pas d'accord avec les commentaires ci-dessus sur le comportement indéfini et la mémoire non allouée: la mémoire pour
int aest à la fois allouée et initialisée, et cette mémoire est accessible via les pointeurschar *qui est autorisé tant queinta au moins 4charde large. La valeur16843009est également correcte (0x01010101). Je pense que la sortie inattendue est simplement que les octets individuels sont imprimés sous forme de caractères (par opposition à leurs valeurs entières) et0x01est un caractère de contrôle.