Quelles sont les opérations prises en charge par le pointeur brut et le pointeur de fonction en C / C ++?

StackOverflow https://stackoverflow.com/questions/1418068

Question

Quelles sont toutes les opérations prises en charge par le pointeur de fonction diffère du pointeur brut? Est-ce que & Gt; , < , < =, > = opérateurs supportés par des pointeurs bruts, si oui, à quoi sert-il?

Était-ce utile?

La solution

Les pointeurs de fonction et les objets sont compilés, mais leur résultat ne peut être cohérent que pour les adresses de sous-objets du même objet complet (vous pouvez comparer les adresses de deux membres d'une classe ou d'un tableau) et si vous le souhaitez. comparer une fonction ou un objet à lui-même.

L'utilisation de std::less<>, std::greater<> etc. fonctionnera avec n'importe quel type de pointeur et donnera des résultats cohérents, même si le résultat de l'opérateur intégré respectif n'est pas spécifié:

void f() { }
void g() { }

int main() {
  int a, b;

  ///// not guaranteed to pass
  assert((&a < &b) == (&a < &b));

  ///// guaranteed to pass
  std::less<int*> lss1;
  assert(lss1(&a, &b) == lss1(&a, &b));
  // note: we don't know whether lss1(&a, &b) is true or false. 
  //       But it's either always true or always false. 

  ////// guaranteed to pass
  int c[2];
  assert((&c[0] < &c[1]) == (&c[0] < &c[1]));
  // in addition, the smaller index compares less:
  assert(&c[0] < &c[1]);

  ///// not guaranteed to pass
  assert((&f < &g) == (&f < &g));

  ///// guaranteed to pass
  assert((&g < &g) == (&g < &g));
  // in addition, a function compares not less against itself. 
  assert(!(&g < &g));

  ///// guaranteed to pass
  std::less<void(*)()> lss2;
  assert(lss2(&f, &g) == lss2(&f, &g));
  // note: same, we don't know whether lss2(&f, &g) is true or false.

  ///// guaranteed to pass
  struct test {
    int a;
  // no "access:" thing may be between these!
    int b;

    int c[1];
  // likewise here
    int d[1];

    test() {
      assert((&a < &b) == (&a < &b));
      assert((&c[0] < &d[0]) == (&c[0] < &d[0]));

      // in addition, the previous member compares less:
      assert((&a < &b) && (&c[0] < &d[0]));
    }
  } t;
}

Tout cela doit cependant être compilé (bien que le compilateur soit libre d'avertir à propos de tout extrait de code qu'il souhaite).

Etant donné que les types de fonctions n'ont pas de valeur sizeof, les opérations définies en fonction de + du type pointee ne fonctionneront pas. Par exemple:

void(*p)() = ...;
// all won't work, since `sizeof (void())` won't work.
// GCC has an extension that treats it as 1 byte, though.
p++; p--; p + n; p - n; 

Le unaire <=> fonctionne sur n’importe quel type de pointeur et ne fera que renvoyer sa valeur, il n’a rien de spécial à ce sujet pour les pointeurs de fonction.

+ p; // works. the result is the address stored in p.

Notez enfin qu'un pointeur sur une fonction pointeur n'est plus un pointeur de fonction:

void (**pp)() = &p;
// all do work, because `sizeof (void(*)())` is defined.
pp++; pp--; pp + n; pp - n;

Autres conseils

Vous pouvez comparer des pointeurs s’ils pointent dans la même allocation. Par exemple, si vous avez deux pointeurs pointant sur des éléments du même tableau, vous pouvez utiliser des opérateurs de comparaison d'inégalité sur ces pointeurs. Par contre, si vous avez deux pointeurs pointant vers des objets différents, alors la comparaison est & "; Undefined &"; Cependant, dans la pratique, la plupart des compilateurs compareront probablement les adresses.

char *text[] = "hello";
const char *e_ptr = strchr(text, 'e');
const char *o_ptr = strchr(text, 'o');
if (e_ptr < o_ptr) { ... }  // this is legal
char *other_text[] = "goodbye";
const char *b_ptr = strchr(other_text, 'b');
if (b_ptr > o_ptr) { ... }  // not strictly legal

# 1 : les pointeurs de fonction peuvent être appelés.

# 2 : les opérateurs relationnels sont pris en charge pour les pointeurs, car vous pouvez les utiliser dans l'arithmétique de pointeur et comparer des adresses. Exemple pratique: parcourir un tableau

int data[5] = { 1, 2, 3, 4, 5 };

// Increment pointer until it reaches the end-address. 
for (int* i = data; i < data + 5; ++i) {
    std::cout << *i << endl; 
}

Les opérateurs < ;, > ;, < =, > = sont pris en charge pour les pointeurs, mais ne peuvent garantir des résultats fiables que si les deux pointeurs comparés sont partie de la même allocation de mémoire (comme comparer deux pointeurs à des index dans une allocation de tableau). Pour ceux-ci, il indique la position relative dans l'allocation (c'est-à-dire, si a & Lt; b, alors a pointe vers un indice inférieur au tableau que b). Pour les pointeurs qui ne sont pas dans la même allocation, le résultat est défini par l'implémentation (et, dans certaines architectures, peut violer des contraintes moins strictes que la compatibilité nécessaire pour les cartes. Par exemple, un pointeur 64 bits pourrait être comparé pour & Lt; ou < !> gt; n'utilisez que les 32 bits inférieurs, si une attribution unique ne peut pas dépasser la taille autorisée pour un pointeur 32 bits). Celles-ci n’ont pas vraiment de sens dans le contexte des pointeurs de fonction car elles ne traitent pas une allocation de mémoire continue.

Autres opérations de pointeur brut: == renvoie true si les pointeurs pointent sur le même objet. - produit le nombre d'octets entre les deux pointeurs (je pense que c'est bien pour la même allocation seulement?). + ne compile pas, cela n'aurait aucun sens.

Pour les pointeurs de fonction, ils peuvent être déréférencés par * et appelés.

Pour les fonctions pointeur-membre, il y a les opérateurs - > * et. *

Un pointeur est représenté par une valeur entière normale. Vous pouvez tout faire avec les pointeurs, ce qui est également autorisé pour tous les autres types numériques. + - * / < < > > ==! = ^ & amp; | ! ~%. J'espère n'avoir rien oublié.

Un pointeur de fonction n'est différent que par le fait qu'il peut être appelé avec l'opérateur ().

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top