답변:
맞아요. C99 §6.5.2.1 / 2에서 :
아래 첨자 연산자 []의 정의는 E1 [E2]가 (* ((E1) + (E2)))와 동일하다는 것입니다.
마법은 없습니다. 1-1 등가입니다. 포인터 (*)를 역 참조 할 때 항상 그렇듯이 유효한 주소를 가리키고 있는지 확인해야합니다.
[]
으로 참조되었습니다 . 초보자를 혼동 하는 가장 좋은 방법은 글을 쓰는 것 대신에 글을 쓰고 그것이 의미하는 바를 추측하는 것을 보는 것입니다. 1[arr]
arr[1]
((E1)+(E2))
하고 예상 값을 가진 (64 비트) 포인터가 될 것입니다.
이것은 arr
배열의 두 번째 요소 또는 이후 요소를 가리키는 포인터 인 경우에만 유효합니다 . 그렇지 않으면 배열 경계 외부의 메모리에 액세스하기 때문에 유효하지 않습니다. 예를 들어 이것은 잘못된 것입니다.
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 비트 주소 지정이있는 32 비트 int 배열 색인이 배열 색인이 명시 적으로 64 비트로 승격되지 않는 한 잘못된 주소 계산을 초래할 수 있다고 말하는 것 같습니다 (예 : ptrdiff_t 캐스트를 통해). 나는 실제로 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의 Array에있는 음수 인덱스에 액세스 할 수 있습니다.
누군가 음수 인덱스를 사용하려는 이유에 대해 두 가지 컨텍스트에서 사용했습니다.
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 까지의 범위에 있지 않는 한 계산 은 정의되지 않습니다 .