Frage

Was sind alle von Funktionszeigern unterstützten Operationen von Rohzeiger unterscheiden? Ist>, <, <=,> = Betreiber von rohen Zeigern unterstützt, wenn so, was die Nutzung ist?

War es hilfreich?

Lösung

Für beide Funktion und Objektzeiger, sie kompilieren, aber ihr Ergebnis garantiert ist nur konsequent für Adressen Unterobjekte des gleichen vollständigen Objekts sein (Sie können die Adressen von zwei Mitgliedern einer Klasse oder einem Array vergleichen), und wenn Sie vergleichen, um eine Funktion oder ein Objekt gegen sich selbst.

Mit std::less<>, std::greater<> und so weiter mit jedem Zeigertyp funktionieren wird, und konsistente Ergebnisse liefern, auch wenn das Ergebnis der jeweiligen eingebauter Operator ist nicht spezifiziert:

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;
}

Alles davon sollte jedoch kompilieren (obwohl der Compiler frei um jeden Code zu warnen Snippet es will).


Da Funktionstypen keinen sizeof Wert haben, Operationen, die in Bezug auf den sizeof des pointee Typs definiert sind, wird nicht funktionieren, dazu gehören:

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; 

Der unäre + funktioniert auf jedem Zeigertyp und den Wert davon nur zurückkehren, gibt es nichts Besonderes es für Funktionszeiger ist.

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

Schließlich ist zu beachten, dass ein Zeiger auf eine Funktion Zeiger ist keine Funktion Zeiger mehr:

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

Andere Tipps

Sie können Zeiger vergleichen, wenn sie in die gleiche Zuteilung zeigen. Zum Beispiel, wenn Sie zwei Zeiger haben auf Elemente des gleichen Array zeigt, können Sie Ungleichheit Vergleichsoperatoren auf diesen Zeiger verwenden. Auf der anderen Seite, wenn Sie zwei Zeiger haben an verschiedenen Objekten zeigen, dann ist der Vergleich „undefiniert“, aber in der Praxis werden die meisten Compiler wahrscheinlich nur die Adressen vergleichen.

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 . Funktionszeiger können aufgerufen werden

# 2 : Die relationalen Operatoren für Zeiger unterstützt werden, weil man sie in Zeiger arithmetics und vergleichen Adressen miteinander verwendet werden können. Praxisbeispiel: Verfahrweg einem Array

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; 
}

Die Operatoren <,>, <=,> = sind für Zeiger unterstützen, sind aber nur zuverlässige Ergebnisse produzieren gewährleistet, wenn die beiden Zeiger verglichen werden, ist Teil der gleichen Speicherzuweisung (wie der Vergleich von zwei Zeigern auf Indizes in einem Array Zuweisung). Für diese gibt es relative Position in der Aufteilung (dh, wenn a verwendet nur die unteren benötigt verletzen 32 Bits, wenn eine Einzelzuweisung nicht die Größe für einen 32-Bit-Zeiger erlaubt überschreiten kann). Diese nicht wirklich Sinn im Zusammenhang mit den Funktionszeigern machen, da sie keine kontinuierliche Speicherzuweisung Adresse.

Andere Rohzeiger Operationen: == gibt true zurück, wenn die Zeiger auf das gleiche Objekt zeigen. - erzeugt die Anzahl von Bytes zwischen den beiden Zeiger (I für die gleiche Zuteilung gut denken nur?). + Nicht kompilieren, da es sinnlos wäre.

Für Funktionszeiger können sie dereferenced von * und aufgerufen werden.

Für Zeiger-to-Mitglied-Funktionen gibt es die Operatoren -> * und *

.

Ein Zeiger wird als normaler ganzzahligen Wert dargestellt. Sie können mit Zeigern alles tun, was auch auf allen anderen numerischen Typen erlaubt. ! + - * / << >> == = ^ & | ! ~%. Ich hoffe, ich vergaß nichts.

Ein Funktionszeiger ist nur anders auf diese Weise, dass sie mit dem Operator () aufgerufen werden können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top