13

次のコードの結果がわかりません:

#include <stdio.h>
#include <conio.h>
int main()
{
   int a[4]={1, 3, 5, 6};
   //suppose a is stored at location 2010
   printf("%d\n", a + 2);
   printf("%d", a++);
   return 0;
}

printf2 番目の関数で次のエラーが発生するのはなぜですか?

error: lvalue required as increment operand

4

7 に答える 7

18

パート1:

配列名は定数です (変更可能な左辺値ではありません)。配列名に値を追加することはできますが、変更することはできません。

式はそれ自体a + 2を変更しませんが、それを行うと、配列名を変更しようとするのと同じです --lvalue エラー。2 番目の printfの式が間違っています - セマンティック フェーズ エラーの例です。次の言語標準をお読みください。 aa++a = a + 1a++

6.3.2.1 左辺値、配列、および関数指定子

724変更可能な左辺値とは、配列型を持たず、不完全な型を持たず、const 修飾された型を持たず、構造体または共用体である場合、メンバー (再帰的に任意の含まれているすべての集約または共用体のメンバーまたは要素) を const 修飾された型で使用します。

729 それが sizeof 演算子または単項演算子のオペランドである場合&、または配列の初期化に使用される文字列リテラルである場合を除き、型「型の配列」を持つ式は型「型へのポインタ」を持つ式に変換されます。配列オブジェクトの最初の要素を指し、左辺値ではありません

パート2:

ほとんどの式の配列名は、最初の要素のアドレスで減衰することに注意してください (配列名が最初の要素へのポインターに減衰しないいくつかの例外をお読みください。@H 2 CO 3で適切に回答されています)。

その結果はa + 2、3 番目の要素のアドレス (または index の要素のアドレス2)になるため、インデックスの値ではなくアドレスa + 2と同じです。&a[2]

アドレスを印刷するには、次のように、%p代わりに使用し、%dアドレスを型キャストvoid* します。

printf("address (a + 2) = %p , &a[2] = %p", (void*)(a + 2), (void*)(&a[2]));

*値を出力するには、次のように防御演算子が必要です。

printf("address *(a + 2) = %d , a[2] = %d", *(a + 2), a[2]);   

パート 3:

a が 2010 の場所に格納されているとします。最初の printf 関数の出力は 2012 ですか?

いいえ、ポインター演算は整数演算とは異なります。私たちが知っているように、配列名はほとんどの式で最初の要素のアドレスに崩壊します。したがってa + 2、値は index にある3番目の要素のアドレスです2。したがって、システムの int サイズが 4 バイトの場合、アドレス値が 2010a + 2であるという仮定に従って、stat が場所 2018 を指しているとします。a

理解するには、10.2 ポインターと配列を読んでください。ポインター演算ポインター演算

于 2013-10-02T05:01:04.553 に答える
2

まず、このプログラムは未定義の動作を呼び出します。非常に多くの回答があり、誰もこれについて言及していないことに少し落胆しています。両方のprintf呼び出しで、引数はポインター%dですが、期待される形式を指定しており、%p である必要がありintます。セクションのC99 ドラフト標準のセクションがフォーマット文字列の段落9について参照する fprintf 関数は、次のように述べています。7.19.6.1 printf

変換指定が無効な場合、動作は未定義です。[...]

あなたの質問に戻ると、インクリメントではオペランド変更可能な lvalueであることが必要であるため、a++はエラーを生成します。6.5.2.4

後置インクリメントまたはデクリメント演算子のオペランドは、修飾または非修飾の実数型またはポインター型を持ち、変更可能な左辺値でなければなりません

6.3.2.1 setion値、配列、関数指定子からわかるように、パラグラフ1は次のように述べています。

[...]変更可能な左辺値は、配列型を持たない左辺値です[...]

于 2013-10-02T12:31:11.397 に答える
2

最初の出力は、コンピューターで整数型がどのように表現されるかに依存すると思います。1 つの整数がメモリ内で 4 バイトを占有する場合、出力は 2018、つまり 2010+2*4 になります。2 番目の printf は、コンパイル エラーを引き起こす可能性があります。

于 2013-10-02T05:25:14.803 に答える