Voici une classe qui documente toutes les fonctions pertinentes sur stderr. J'essaie les trois expressions que vous mentionnez dans un programme :
#include
#include
using namespace std;
struct PtrT;
ostream& operator<<(ostream& os, const PtrT& ptr);
///
/// Une classe qui définit les post- et pre-incréments ainsi que le déréférencement.
/// Elle documente tous les appels de fonctions, y compris les constructeurs et destructeur.
///
struct PtrT
{
string name; //< Fournit une identité.
int val = 0;
PtrT(string n) : name(n)
{
cerr << "PrT(\"" << name << "\", " << val << "). ";
}
///
/// Fait une copie de l'élément de droite, mais préfixe le
/// nouveau nom avec "copy_of"
///
PtrT(const PtrT &rhs) : name("copy_of_" + rhs.name), val(rhs.val)
{
cerr << "PrT(" << rhs << "). ";
}
~PtrT()
{
cerr << "~PrT(" << *this << "). ";
}
///
/// Post-incrément, en incrémentant val.
///
/// Une copie de *this, avec l'ancienne val.
PtrT operator++(int)
{
cerr << "post-incr " << *this << ". ";
PtrT returnVal(*this);
++val;
cerr << "post-incr : this is now " << *this
<< ", but will return " << returnVal << ". ";
return returnVal;
}
///
/// Pré-incrément, en incrémentant val
///
/// *this avec la val incrémentée.
PtrT& operator++()
{
cerr << "pre-incr " << *this << ", val will be " << val + 1 << ". ";
++val;
return *this;
}
///
/// Opérateur de "déréférencement"
///
/// Une référence à val
int& operator*()
{
cerr << "deref " << *this << ". ";
return val;
}
};
///
/// Fonction de commodité qui affiche le nom avec val entre parenthèses
///
ostream& operator<<(ostream& os, const PtrT &ptr)
{
os << ptr.name << "(" << ptr.val << ")";
return os;
}
int main()
{
PtrT p("p");
cerr << "Before assignment to i: " << p << endl;
cerr << "\n--------------- *++p ------------------\n";
// Incrémente p, renvoie une référence à val après l'incrémentation
int i = *++p;
cerr << "i now: " << i << ", " << p << endl;
cerr << "\n--------------- ++*p ------------------\n";
// renvoie val, incrémente int via une référence
i = ++*p;
cerr << "i now: " << i << ", " << p << endl;
cerr << "\n--------------- *p++ ------------------\n";
// fait une copie de p, incrémente p.val, renvoie une référence à val de la copie de p
i = *p++;
cerr << "i now: " << i << ", " << p << endl;
}
L'opérateur de sortie de la classe imprime le nom de l'objet avec la valeur de son membre int, val
, entre parenthèses. La sortie du programme est la suivante :
PrT("p", 0). Before assignment to i: p(0)
--------------- *++p ------------------
pre-incr p(0), val will be 1. deref p(1). i now: 1, p(1)
--------------- ++*p ------------------
deref p(1). i now: 2, p(2)
--------------- *p++ ------------------
post-incr p(2). PrT(p(2)). post-incr: this is now p(3), but will return copy_of_p(2). deref copy_of_p(2). ~PrT(copy_of_p(2)). i now: 2, p(3)
~PrT(p(3)).
- Le premier cas,
*++p
, est simple : incrémenter, déréférencer, c'est tout.
- Dans le deuxième cas,
++*p
, l'incrémentation est l'opérateur intégré d'incrémentation d'entier, appliqué au résultat du déréférencement, une référence à un int, et non à la classe (notez qu'il n'y a pas de sortie d'opérateur d'incrémentation) ! Mais parce que la référence pointe vers le membre de classe, le même effet est obtenu : p.val
est incrémenté, comme le montre p(2)
.
- Le troisième cas,
*p++
, est le plus intéressant. Comme c'est d'usage, la fonction de l'opérateur incrémente internement l'objet original mais retourne une copie avec la valeur non incrémentée. Cette copie est déréférencée, renvoyant la val non incrémentée, puis détruite. Cependant, l'original p
a une valeur de 3 après l'impression et, à la fin, est détruit également.
6 votes
Vous avez manqué le quatrième :
(*ptr)++
(les parenthèses sont nécessaires pour lever l'ambiguïté avec*ptr++
)15 votes
Parce que vous avez incrémenté le pointeur avant de l'imprimer. Vous vouliez while(*p) et printf("%c", *p++);
0 votes
Super questions pour l'interview. Utilisation pratique limitée. J'aimerais que le langage C n'ait pas ces pointeurs :)
5 votes
@Himanshu Si cela embrouille votre candidat à l'entrevue, essayez ceci : Avoir un pointeur global,
char* p
, pointant vers une chaîne de caractères unique valide. Ensuite, avoir une fonctionfn(char ch)
qui imprime à la fois le paramètre ch et le caractère actuel pointé parp
. Maintenant, invoquezfn(*p++);
Q : Est-ce quefn
imprime le même caractère deux fois ? Vous seriez surpris du nombre de professeurs qui répondent mal à cette question.1 votes
Puisque p pointe vers une chaîne littérale, vous devriez écrire
const char* p = "Bonjour";
0 votes
@WhozCraig je suis l'interviewé :) et oui, c'est encore plus vrai
0 votes
Lire Pointeur
*++*ptr
utilisation aussi je pense vous aider davantage0 votes
Il est utilisé pour donner un accent français à votre exemple "Hello World"...