8

*参照/逆参照 (またはそれらを呼び出すために選択したもの) 演算子を利用するいくつかの C コードに出くわしまし&た。私はそれに困惑しています。これを行う理由はありますか?&*foo*&bar

4

3 に答える 3

15

はい、有意義に使用できます。有効なユースケースは、マクロ定義でマクロ引数が要件に一致することを確認することです。

&*fooがポインター型であることを確認しfooます (おそらく、配列または関数型からの暗黙的な変換の後)。

*&foofooそれが左辺値式であることを検証します。

たとえば、確かに非常に単純な例なので、マクロの乱用かもしれません。

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
}
于 2016-07-01T19:10:33.753 に答える
2
于 2016-07-01T19:12:04.233 に答える
0
  1. &*ptrコンパイラへのヒントが含まれていますptr != NULL(それ以外の場合*ptrは未定義の動作を意味するため)。

  2. *&単に、補助ポインタ変数が削除されたメンテナンス変更の結果である可能性があります。

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

    ip上記のコードを単純に置き換えると、&x.iStackOverflow で次のような疑問が生じる可能性のあるコードが生成されます。

    struct {
        int i;
        double
    } x;
    
    void foo() {
        ...
        *&x.i = 1;  // <---
        ...
    }
    
  3. 同様に&*、左辺値をポインターに置き換えたリファクタリングの変更によって導入される可能性があります。

    リファクタリング前:

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

    サーバー設定コードを独自の関数に抽出した後:

    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);
        ...
    }
    
于 2016-07-03T20:29:22.307 に答える