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?
risposta
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
}
Potresti fornire esempi più concreti? Aiuterà a capire meglio la tua risposta. Grazie. –
@StanislavPankevich Qualcosa di simile? :) – hvd
Molto utile, grazie. Potresti anche aggiungere un esempio per '* & foo verifica che foo sia un'espressione lvalue.? –
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 .
Quando vorresti farlo? Non ho mai detto a me stesso, "Mi auguro che questo non fosse un valore". – yellowantphil
@yellowantphil Questo dipende, ma in caso di controlli di uguaglianza, può aiutare a rilevare problemi '=' vs '=='. –
@SouravGhosh Non ho mai visto persone scrivere '& * p1 == & * p2' per capirlo. Hai? – hvd
&*ptr
contiene un suggerimento per il compilatore cheptr != NULL
(altrimenti*ptr
significherebbe comportamento indefinito).*&
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; // <--- ... }
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); ... }
ci mostri un caso ad esempio (_non esempio _codice)? –
Viene utilizzato in assegnazioni di variabili semplici. –