1
int main(int argc, char * argv[]) {
  int       a = 10;
  int *    sp = &a;
  int * * dp1 = &sp;
  int * * dp2 = &&a;           // NG
  int * * dp3 = &(&a);         // NG
  int * * dp4 = &((int *) &a); // NG
}
$ cc test.c
test.c: In function ‘main’:
test.c:6:17: error: lvalue required as unary ‘&’ operand
   int * * dp3 = &(&a);         // NG
                 ^
test.c:7:17: error: lvalue required as unary ‘&’ operand
   int * * dp4 = &((int *) &a); // NG
                 ^
test.c:5:3: error: label ‘a’ used but not defined
   int * * dp2 = &&a;           // NG
   ^
4

4 に答える 4

8

使えない理由&&a

&変数のアドレスを提供し&a、変数ではないためです。

C 11 ドラフトでは、次のように指定されています。

6.5.3.2 アドレスおよび間接演算子

制約

1 単項 & 演算子のオペランドは、関数指定子、[] または単項 * 演算子の結果、またはビットフィールドではなく、レジスタ ストレージ クラスで宣言されていないオブジェクトを指定する左辺値のいずれかでなければなりません。指定子。

[...]

セマンティクス

3 単項 & 演算子は、そのオペランドのアドレスを生成します。[...]

この「制限」を回避するには、次のような複合リテラルを使用して一時ストレージを導入できます (少なくとも C99 を想定)。

int a = 42; 
int ** ppa = &((int *){&a});

以下のエラーメッセージを参照する補足として:

test.c:5:3: error: label ‘a’ used but not defined
   int * * dp2 = &&a;           // NG
   ^

&&gcc (およびおそらく他のもの) は、オペラントがラベルを識別する場合に単一のオペラントで演算子を使用できるようにする C 標準の拡張機能を定義します。(詳細はこちら: https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html )

例:

void * pv = &&lbl;

goto *pv;

/* some dead code  */

lbl:;

/* living code again here */
于 2015-06-18T09:51:43.243 に答える
5

@UnWindが言うように、値のアドレス(&aで指定)ではなく変数のアドレスのみを取得でき、さらに && はブール値ANDであるためです。

于 2015-06-18T09:51:33.870 に答える
3

すべてのステートメントで、この部分:&aは数値として扱われます (変数のアドレスを取得するため)。

したがって、最初の 2 つのエラーについては次のようになります。

エラー: 左辺値は単項 '&' として必要です オペランド

最初の演算子はビットごとの AND&演算子として扱われるため、その前に値があると想定されます。(つまり)。2 & 3

最後のエラーの場合:

エラー: ラベル 'a' が使用されていますが、定義されていません

2つのため、をラベルとして&&扱っているという事実によるものです( alk's answerを参照)。a

あなたが達成したいこと(アドレスのアドレスを取得する)は不可能です。これは、「定数値」のアドレスを取得できないためです。これ&aは、すでに値であり、変数のアドレスのみであるためです。

于 2015-06-18T09:57:59.203 に答える
2

&varあなたの変数のアドレスをあなたに与えるので、私はあなたが何を期待&&varしているのか、アドレスのアドレスがわからないでしょうか? 私が間違っている場合は修正してください。

于 2015-06-18T09:50:46.217 に答える