回答:
それは正しいです。C99§6.5.2.1/ 2から:
添字演算子[]の定義は、E1 [E2]が(*((E1)+(E2)))と同一であることです。
魔法はありません。1-1相当です。いつものようにポインター(*)を逆参照するときは、それが有効なアドレスを指していることを確認する必要があります。
[]
は、ポインタ演算の構文糖として参照されていました。初心者を混乱させるお気に入りの方法は、1[arr]
-の代わりにarr[1]
- 書いて、それが何を意味するのかを推測することです。
((E1)+(E2))
され、期待値を持つ(64ビット)ポインターになると思います。
これはarr
、が配列の2番目の要素または後の要素を指すポインターである場合にのみ有効です。それ以外の場合は、配列の境界外のメモリにアクセスするため、無効です。したがって、たとえば、これは間違っています。
int arr[10];
int x = arr[-2]; // invalid; out of range
しかし、これは大丈夫です:
int arr[10];
int* p = &arr[2];
int x = p[-2]; // valid: accesses arr[0]
ただし、負の添え字を使用することはまれです。
int arr[10];
その前に他の要素と構造体の一部で、arr[-2]
潜在的に明確に定義された可能性があり、それが基づいている場合は、決定することができるoffsetof
等、
If one is sure that the elements exist, it is also possible to index backwards in an array; p[-1], p[-2], and so on are syntactically legal, and refer to the elements that immediately precede p[0]. Of course, it is illegal to refer to objects that are not within the array bounds.
それでも、あなたの例は私がそれを理解するのに役立ちます。ありがとう!
これがどれほど信頼できるかはわかりませんが、64ビットシステム(LP64と思われる)での負の配列インデックスに関する次の警告を読んだだけです。http://www.devx.com/tips/Tip/41349
著者は、配列インデックスが明示的に64ビットに昇格されない限り(たとえば、ptrdiff_tキャストによって)、32ビットint配列インデックスと64ビットアドレス指定が不適切なアドレス計算を引き起こす可能性があると言っているようです。私は実際にgcc 4.1.0のPowerPCバージョンで彼の性質のバグを見ましたが、それがコンパイラのバグ(つまり、C99標準に従って動作するはず)であるのか、正しい動作(つまり、インデックスは64へのキャストが必要)であるのかわかりません。正しい動作のためのビット)?
質問への回答はわかっていますが、この説明を共有することに抵抗がありませんでした。
コンパイラ設計の原則を覚えています。aがint配列で、intのサイズが2で、aのベースアドレスが1000であるとします。
どのようa[5]
に動作します->
Base Address of your Array a + (index of array *size of(data type for array a))
Base Address of your Array a + (5*size of(data type for array a))
i.e. 1000 + (5*2) = 1010
この説明は、配列の負のインデックスがCで機能する理由でもあります。
つまり、アクセスa[-5]
すると、
Base Address of your Array a + (index of array *size of(data type for array a))
Base Address of your Array a + (-5 * size of(data type for array a))
i.e. 1000 + (-5*2) = 990
これは、場所990にあるオブジェクトを返します。このロジックにより、Cの配列の負のインデックスにアクセスできます。
誰かが負のインデックスを使用する理由について、私は2つのコンテキストでそれらを使用しました。
あなたにcomb [1] [-1] = 0を伝える組み合わせ番号の表を持っている; テーブルにアクセスする前にいつでもインデックスをチェックできますが、これにより、コードがすっきりして高速に実行されます。
テーブルの最初にセンチネルを置く。たとえば、次のようなものを使用したい場合
while (x < a[i]) i--;
しかし、あなたはそれi
がポジティブであることも確認すべきです。
解決策:そうすることa[-1]
で-DBLE_MAX
、x<a[-1]
常にfalseになります。
#include <stdio.h>
int main() // negative index
{
int i = 1, a[5] = {10, 20, 30, 40, 50};
int* mid = &a[5]; //legal;address,not element there
for(; i < 6; ++i)
printf(" mid[ %d ] = %d;", -i, mid[-i]);
}
somearray-2
結果が最初からsomearray
最後まで1の範囲にない限り、計算は未定義です。