2016-07-01 4 views
8

&*foo*&bar과 같이 참조/참조 해제 (또는 사용자가 선택하는 모든 연산자) 연산자 *&을 동시에 사용하는 C 코드를 발견했습니다. 나는 그것에 당혹 스럽다. 이것을 할 어떤 이유가 있습니까?C 코드에서 * & 및 & *를 사용할 이유가 있습니까?

+2

당신이 우리에게 예를 들어 케이스 (_not 예 code_)을 보여줄 수 :

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

자체의 기능에 서버 설치 코드를 추출 후? –

+0

간단한 변수 할당에 사용되고 있습니다. –

답변

15

예, 유효하게 사용할 수 있습니다. 유효한 매크로 사용 예는 매크로 인수가 요구 사항과 일치하는지 확인하는 것입니다.

&*foofoo이 포인터 유형 (가능한 경우 배열 또는 함수 유형에서 암시 적 변환 후)인지 확인합니다.

*&foofoo이 1 값 표현임을 검증합니다.

예를 들어, 일반적으로 인정 하듯이 매크로 학대의 비트 될 수 있도록 간단한 예 :

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

구체적인 예를 제공해 주시겠습니까? 당신의 대답을 더 잘 이해하는 데 도움이 될 것입니다. 감사. –

+0

@StanislavPankevich이게 뭔가요? :) – hvd

+0

매우 도움이됩니다. 감사합니다. '* & foo에 대한 예제를 추가해도 foo가 lvalue 표현식임을 검증 할 수 있습니까? ' –

2

그렇게 할 수있는 유일한 의미있는 이유는 좌변로 표현을 치료 중지하는 것입니다.

인용 C11 장 §6.5.3.2

& 단항 연산자는 오퍼랜드의 어드레스를 산출한다. 피연산자 유형이 인 경우 '유형' ', 의 결과가 ' '포인터 유형' ''입니다. 피연산자는 단항 * 연산자의 결과 인 경우 그 조작도없고 & 운영자가 평가되고, 모두 생략 것처럼 연산자에 대한 제약이 여전히 을 적용하는 것을 제외하고 그 결과 인 결과는 좌변 아니다 .

+4

언제 그렇게하고 싶습니까? 나는 결코 나 자신에게 말하지 않았다, "나는 이것이 확실히 lvalue가 아니길 바란다." – yellowantphil

+0

@yellowantphil 이것은 동일하지만, 평등 검사의 경우에는'='vs'=='문제를 감지하는 데 도움이 될 수 있습니다. –

+3

@SouravGhosh 나는 사람들이'& * p1 == & * p2'라고 쓰는 것을 본 적이 없다. 너? – hvd

0
  1. &*ptrptr != NULL (*ptr 그렇지가 정의되지 않은 동작을 의미) 컴파일러에 대한 힌트가 포함되어 있습니다. 이러한 문제를 낳을 수

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

    이 노골적 &x.i 결과와 상기 코드 ip에 대체 코드 :

  2. *&는 보조 포인터 변수가 제거 된 유지 변화 단순히 결과 일 수있다 대한 stackoverflow :

    마찬가지로 &*
    struct { 
        int i; 
        double 
    } x; 
    
    void foo() { 
        ... 
        *&x.i = 1; // <--- 
        ... 
    } 
    
  3. 교체 리팩토링 변화에 의해 도입 될 수있다 포인터가있는 lvalue.리팩토링하기 전에

    :

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