2016-07-01 31 views
8

Mi sono imbattuto in qualche codice C che utilizza gli operatori di riferimento/dereferenziazione (o qualsiasi altra cosa si sceglie chiamarli), * e &, allo stesso tempo, come &*foo e *&bar. Ne sono perplesso. C'è qualche ragione per farlo?C'è un motivo per usare * & or & * nel codice C?

+2

ci mostri un caso ad esempio (_non esempio _codice)? –

+0

Viene utilizzato in assegnazioni di variabili semplici. –

risposta

15

Sì, possono essere utilizzati in modo significativo: un caso di utilizzo valido è nelle definizioni macro per verificare che l'argomento macro corrisponda ai requisiti.

&*foo verifica che foo sia un tipo di puntatore (eventualmente dopo una conversione implicita da un array o un tipo di funzione).

*&foo verifica che foo sia un'espressione lvalue.

Ad esempio, certamente un esempio così semplice che potrebbe essere un po 'di abuso macro:

void f(int *); 
#define F(x) (f(&*(x))) 

void g(int *); 
#if A 
#define G(x) (g(x), (x)=0) 
#elif B 
#define G(x) (g(*&(x))) 
#endif 

void h(int *p, int i) { 
    f(p); // okay 
    F(p); // still okay, does the same thing as f(p) 
    f(i); // typically just a compiler warning 
    F(i); // pretty much always a compiler error 

    g(p); // okay 
    G(p); // okay 
    g(p+0); // okay 
    G(p+0); // error if A because of the modification 
      // should be an error if B even without modification 
} 
+1

Potresti fornire esempi più concreti? Aiuterà a capire meglio la tua risposta. Grazie. –

+0

@StanislavPankevich Qualcosa di simile? :) – hvd

+0

Molto utile, grazie. Potresti anche aggiungere un esempio per '* & foo verifica che foo sia un'espressione lvalue.? –

2

L'unico motivo significativo per farlo è quello di smettere di trattare l'espressione come un lvalue.

Citando C11, capitolo §6.5.3.2

Il unario & operatore cede l'indirizzo del suo operando. Se l'operando ha tipo '' tipo '', , il risultato è di tipo "" per puntare a "". Se l'operando è il risultato di un operatore univoco , né l'operatore né l'operatore & vengono valutati e il risultato è come se entrambi fossero omessi, eccetto che i vincoli sugli operatori continuano a essere applicati e il risultato non è un lvalue .

+4

Quando vorresti farlo? Non ho mai detto a me stesso, "Mi auguro che questo non fosse un valore". – yellowantphil

+0

@yellowantphil Questo dipende, ma in caso di controlli di uguaglianza, può aiutare a rilevare problemi '=' vs '=='. –

+3

@SouravGhosh Non ho mai visto persone scrivere '& * p1 == & * p2' per capirlo. Hai? – hvd

0
  1. &*ptr contiene un suggerimento per il compilatore che ptr != NULL (altrimenti *ptr significherebbe comportamento indefinito).

  2. *& può essere semplicemente il risultato di un cambiamento di manutenzione in cui è stata eliminata una variabile puntatore ausiliario:

    struct { 
        int i; 
        double 
    } x; 
    
    void foo() { 
        int* ip = &x.i; 
        ... 
        *ip = 1; 
        ... 
    } 
    

    semplicemente sostituendo nel codice precedente ip con &x.i risultati in codice che può dar vita ad una tale domanda su StackOverflow:

    struct { 
        int i; 
        double 
    } x; 
    
    void foo() { 
        ... 
        *&x.i = 1; // <--- 
        ... 
    } 
    
  3. Analogamente &* può essere introdotto da un cambiamento refactoring che ha sostituito lvalue con un puntatore.

    Prima di refactoring:

    int main() { 
        struct sockaddr_in serv_addr; 
    
        ... 
        bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); 
        ... 
    } 
    

    Dopo l'estrazione del codice di configurazione del server in una funzione a sé stante:

    void setup_server(struct sockaddr_in* serv_addr) { 
        ... 
        bind(sockfd, (struct sockaddr *) &*serv_addr, sizeof(*serv_addr)); 
        ... 
    } 
    
    int main() { 
        struct sockaddr_in serv_addr; 
    
        ... 
        setup_server(&serv_addr); 
        ... 
    } 
    
Problemi correlati