2016-07-01 19 views
8

Ich bin auf einige C-Code, die Verwendung der Referenz/Dereferenz (oder was auch immer Sie wählen, um sie zu nennen) Operatoren, * und &, zur gleichen Zeit, wie &*foo und *&bar. Ich bin verwirrt. Gibt es einen Grund, dies zu tun?Gibt es einen Grund, * & oder & * im C-Code zu verwenden?

+2

Können Sie uns ein Beispiel Fall (_not Beispiel Code_)? –

+0

Es wird in einfachen Variablenzuweisungen verwendet. –

Antwort

15

Ja, sie können sinnvoll verwendet werden: Ein gültiger Anwendungsfall ist in Makrodefinitionen, um zu überprüfen, ob das Makroargument den Anforderungen entspricht.

&*foo überprüft, ob foo ein Zeigertyp ist (möglicherweise nach einer impliziten Konvertierung von einem Array oder Funktionstyp).

*&foo überprüft, dass foo ein lvalue Ausdruck ist.

Zum Beispiel zugegebenermaßen ein Beispiel so einfach, dass es ein bisschen von Makro Missbrauch sein könnte:

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

Könnten Sie bitte konkretere Beispiele geben? Wird helfen, Ihre Antwort besser zu verstehen. Vielen Dank. –

+0

@StanislavPankevich So ähnlich? :) – hvd

+0

Sehr hilfreich, danke. Könnten Sie auch ein Beispiel für '* & foo hinzufügen, dass foo ein lvalue-Ausdruck ist.' –

2

Der einzige sinnvolle Grund, dies zu tun ist, den Ausdruck als lvalue zu stoppen Behandlung.

Zitiert C11 Kapitel §6.5.3.2

unären Operator & liefert die Adresse des Operanden. Wenn der Operand den Typ '' type '', hat, hat das Ergebnis den Typ '' Zeiger auf den Typ ''. Wenn der Operand das Ergebnis eines unären Operators *, ist, wird weder dieser Operator noch der Operator & ausgewertet, und das Ergebnis ist so, als wären beide weggelassen, mit der Ausnahme, dass die Einschränkungen für die Operatoren weiterhin gelten und das Ergebnis kein lvalue ist .

+4

Wann möchten Sie das tun? Ich habe mir nie gesagt: "Ich wünschte mir, das wäre kein Wert." – yellowantphil

+0

@yellowantphil Das ist abhängig, aber im Falle von Gleichheitsüberprüfungen kann es helfen, '=' vs '==' Probleme zu erkennen. –

+3

@SouravGhosh Ich habe noch nie gesehen, dass Leute '& * p1 == & * p2' schreiben, um das zu verstehen. Hast du? – hvd

0
  1. &*ptr enthält einen Hinweis für den Compiler, die ptr != NULL (da sonst *ptr undefiniertes Verhalten bedeuten würde).

  2. *& kann einfach ein Ergebnis einer Wartungsänderung, wo eine Hilfszeigervariable eliminiert wurde:

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

    ohne weiteres in dem obigen Code ersetzt ip mit &x.i Ergebnisse in Code, der Geburt auf eine solche Frage geben kann, Stackoverflow:

    struct { 
        int i; 
        double 
    } x; 
    
    void foo() { 
        ... 
        *&x.i = 1; // <--- 
        ... 
    } 
    
  3. Ähnlich &* kann durch eine Refactoring Änderung eingeführt werden, die ersetzt Lvalue mit einem Zeiger.

    Vor Refactoring:

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

    Nachdem das Server-Setup-Code in eine eigene Funktion zu extrahieren:

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