Quali sono le operazioni supportate dal puntatore non elaborato e dal puntatore a funzione in C / C ++?

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

Domanda

Quali sono le operazioni supportate dal puntatore a funzione differisce dal puntatore non elaborato? È & Gt; , < , < =, > = operatori supportati da puntatori non elaborati in caso affermativo, a che serve?

È stato utile?

Soluzione

Sia per i puntatori di funzioni che per quelli di oggetti, vengono compilati ma il loro risultato è garantito solo coerente per gli indirizzi con oggetti secondari dello stesso oggetto completo (è possibile confrontare gli indirizzi di due membri di una classe o di un array) e se si confronta una funzione o un oggetto con se stesso.

L'uso di std::less<>, std::greater<> e così via funzionerà con qualsiasi tipo di puntatore e fornirà risultati coerenti, anche se il risultato del rispettivo operatore incorporato non è specificato:

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

Tutto ciò dovrebbe essere compilato (anche se il compilatore è libero di avvisare di qualsiasi frammento di codice che desidera).


Poiché i tipi di funzione non hanno valore sizeof, le operazioni definite in + del tipo di punta non funzioneranno, queste includono:

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; 

L'unario <=> funziona su qualsiasi tipo di puntatore e ne restituirà semplicemente il valore, non c'è nulla di speciale nei puntatori a funzione.

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

Infine, nota che un puntatore a una funzione puntatore non è più un puntatore a funzione:

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

Altri suggerimenti

Puoi confrontare i puntatori se puntano nella stessa allocazione. Ad esempio, se si hanno due puntatori che puntano su elementi dello stesso array, è possibile utilizzare operatori di confronto delle disuguaglianze su tali puntatori. D'altra parte, se hai due puntatori che puntano su oggetti diversi, allora il confronto è & Quot; non definito & Quot; anche se, in pratica, la maggior parte dei compilatori probabilmente confronterà solo gli indirizzi.

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 : è possibile richiamare i puntatori a funzione.

# 2 : gli operatori relazionali sono supportati per i puntatori perché è possibile utilizzarli nell'aritmetica dei puntatori e confrontare gli indirizzi tra loro. Esempio pratico: attraversare un 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; 
}

Gli operatori < ;, > ;, < =, > = sono supportati per i puntatori, ma sono garantiti per produrre risultati affidabili solo se i due puntatori confrontati sono parte della stessa allocazione di memoria (come confrontare due puntatori con gli indici in un'allocazione di array). Per questi, indica la posizione relativa nell'allocazione (cioè, se a & Lt; b, quindi a sta indicando un indice inferiore nella matrice di b). Per i puntatori che non si trovano nella stessa allocazione, il risultato è definito dall'implementazione (e in alcune architetture, può violare una rigorosa meno della compatibilità necessaria per le mappe. Ad esempio, un puntatore a 64 bit potrebbe essere confrontato per & Lt; oppure < !> gt; utilizzando solo i 32 bit inferiori, se una singola allocazione non può superare le dimensioni consentite per un puntatore a 32 bit). Questi non hanno davvero senso nel contesto dei puntatori a funzioni poiché non affrontano un'allocazione di memoria continua.

Altre operazioni puntatore non elaborato: == restituisce vero se i puntatori puntano allo stesso oggetto. - produce il numero di byte tra i due puntatori (mi sembra buono solo per la stessa allocazione?). + non viene compilato, poiché sarebbe privo di significato.

Per i puntatori a funzioni, possono essere dereferenziati da * e chiamati.

Per le funzioni da puntatore a membro, ci sono gli operatori - > * e. *

Un puntatore è rappresentato come un normale valore intero. Puoi fare tutto con i puntatori che sono consentiti anche su tutti gli altri tipi numerici. + - * / < < gt &; gt &; ==! = ^ & amp; | ! ~%. Spero di non aver dimenticato nulla.

Un puntatore a funzione è diverso solo per il fatto che può essere chiamato con l'operatore ().

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top