6

なぜこれがコンパイルできるのか疑問に思っています:

#include <stdio.h>
int main(int argc, char const* argv[])
{
    char *str[3];
    char x = 'a';
    char *px;
    px = &x;
    str[0] = px;
    return 0;
}

これはできませんが:

#include <stdio.h>
int main(int argc, char const* argv[])
{
    char *str[3];
    str[1] = &'a';
    return 0;
}

decla.c: In function ‘main’:
decla.c:9:14: error: lvalue required as unary ‘&amp;’ operand
4

5 に答える 5

9

少し単純化すると、変数のアドレスしか取得できません。リテラル like'a'は変数ではありません。

ISO/IEC 9899:2011 §6.5.3.2 アドレスおよび間接演算子

制約

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

標準からの引用は、次を使用できることを意味します。

  • &array[i]
  • &*ptr
  • &function

または変数、または構造体または共用体型のメンバー:

  • &var
  • &ptr->member
  • &obj.member

等。

于 2013-08-09T21:25:02.473 に答える
7

いくつかの回答は、名前付き変数のアドレスしか取得できないと言っていますが、それは完全に正しいわけではありません.C99以降を使用している場合は、複合リテラルまたは複合リテラルのフィールドのアドレスも取得できます. 通常、これは、呼び出し中にのみ作成する必要がある構造体への in ポインターを受け取る関数を呼び出す場合などに役立ちます。例:draw(&(struct point){ 5, 10 });

スカラーのアドレスを取得するためにこれを使用できるいくつかの方法 [説明で編集]:

// create a char array containing only 'a', dereference to get 'a', and take its address
char *c = &*(char[]){'a'};  

// same as above, but using an array subscript
char *c = & (char[]){'a'}[0];        

/* create a literal for one unnamed struct containing only the char member "c",
   access .c, and take its address all in the same statement */        
char *c = &(struct{char c;}){'a'}.c;

そして、包含ブロックの期間中、*c は 'a' と等しくなります。

ただし、複合リテラルを使用してリテラルへのアドレスを取得するより簡潔でより一般的な方法は、1 つの要素のみで配列リテラルを宣言することです。これは、代入時に通常どおりポインターに減衰します。

char *c = (char[]){'a'};

そして、これはジョブのかなり典型的な構文です。しかし、結局のところ、この言語を使用すると、さらに直接的でやや非直感的なことを実行できます。つまり、スカラー型の複合リテラルを宣言できます。これにより、上記のすべてがより明白になります。

char *c = &(char){'a'};

あなたの場合、

#include <stdio.h>
int main(int argc, char const* argv[])
{
    char *str[3];
    str[1] = &(char){'a'};
    return 0;
}

これは「&」よりも少し冗長であり、実際には一時変数を割り当てるよりも数キー少ないだけですが、それはあります。

于 2013-08-10T00:28:46.167 に答える
5

問題は、 operator のアドレスがnamesでのみ機能することです。

char character = 'a';
str[1] = &character;

うまくいくはずです。

機能しない理由&'a'は、値にアドレスさえあるという保証がないためです。コードページからレジスタに直接ロードされる可能性があります。その場合、参照可能なメモリにないか、少なくとも逆参照する必要があるメモリにありません。

于 2013-08-09T21:25:55.820 に答える
1

最初のスニペットは、変数のアドレスを取得しているため、正常に機能しています。

2 番目のコード スニペット:-

str[1] = &'a'; 

これは正しい方法ではありません。「a」は変数ではありません。演算子のアドレス演算子は名前に作用します。これを機能させたい場合は、次のように変更します。

 char c = 'a';
 str[1] = &c;
于 2013-08-09T21:26:43.473 に答える
1

Jonathan が言ったように、変数のアドレスしか取得できません。内部では、'a' は実際には単なる短い整数 ('a' の ASCII 値) です。したがって、これができない理由と同じです。

str[1] = &9;
于 2013-08-09T21:27:04.793 に答える