연속 배열

Aug 26 2020

C18 표준의 한 문장이 궁금합니다.

두 포인터는 둘 다 널 포인터 인 경우에만 동일하게 비교됩니다. 둘 다 동일한 객체 (객체에 대한 포인터와 시작 부분의 하위 객체 포함) 또는 함수에 대한 포인터이고, 둘 다 동일한 배열의 마지막 요소를 지나서 하나에 대한 포인터입니다. 객체 또는 하나는 한 배열 객체의 끝을 지나서 하나에 대한 포인터이고 다른 하나 는 주소 공간에서 첫 번째 배열 객체 바로 다음에 발생 하는 다른 배열 객체 의 시작에 대한 포인터 입니다. § 6.5.9 6

배열 뒤의 객체가 반드시 다른 배열이어야하는 이유는 무엇입니까? 단순히 (AN 같은 배열베이스 타입과 동일한 타입의 객체 수없는 int바로 다음의 int[])?

이 코드를 시도한 것은 당연합니다.

#include <stdio.h>

struct test { int arr[10]; int i; };

int main() {
    struct test t;
    int *p, *q;
    p = t.arr + 10;
    q = &t.i;
    if (p == q)
        printf("Equal pointers.");
    return 0;
}

그리고 동일한 포인터를 생성합니다. 이 동작은 전혀 보장되지 않고 구현 정의 우연 일 뿐입니 까?

답변

24 chux-ReinstateMonica Aug 26 2020 at 17:41

OP : 배열 뒤의 객체가 반드시 다른 배열이어야하는 이유는 무엇입니까?

그렇지 않습니다. "... 다른 어레이의 시작 ..."은 단순화입니다. 다음 사양은 다음과 같습니다.

이러한 연산자의 목적을 위해 배열의 요소가 아닌 개체에 대한 포인터는 개체 유형이 요소 유형 인 길이 1 인 배열의 첫 번째 요소에 대한 포인터와 동일하게 작동합니다. C17dr § 6.5.9 7


OP : 단순히 (AN 같은 배열의 기본 유형과 동일 유형의 객체가 될 수 없습니다 int즉시 다음을 int[])?

예.

8 th33lf Aug 26 2020 at 17:26

첫째, 여기에 배열을 지정해도 단일 객체를 제외 / 금지하지 않습니다. 메모리의 단일 개체는 크기 1의 배열과 구별 할 수 없습니다.

( 편집 : 포인터를 언급 할 때 명시 적으로 언급하는 표준 인용에 대해이 답변 을 읽으십시오 )

둘째, 표준은 또한 규칙이 적용되는 시나리오를 나타내는 다음 각주를 사용하여 인용 한 진술을 명확히하려고합니다.

두 개체는 더 큰 배열의 인접 요소이거나 그 사이에 패딩이없는 구조의 인접 멤버이거나 관련이 없더라도 구현시 배치하도록 선택했기 때문에 메모리에서 인접 할 수 있습니다.

이 모든 것을 종합하면 표준이 여기서 말하는 것은 일반적으로 서로 다른 객체에 대한 두 포인터가 동일하게 비교되지 않아야한다는 것입니다. 그러나 메모리의 배열 객체 너머에 하나를 가리키는 것이 합법적이므로 해당 위치에 다른 (배열) 객체가있는 경우 이러한 포인터가 인접한 객체에 대한 포인터와 동일하게 비교하는 것은 여전히 ​​합법적입니다. 이제 정렬 선택과 패딩으로 인해이 위치에 유효한 객체가있을 수도 있고 없을 수도 있지만, 하나가있는 경우 이러한 포인터가 동일하게 비교하는 것이 허용됩니다.

귀하의 예에서 배열을 char로 변경하면 컴파일러가 int를 4 바이트 (대부분의 32 또는 64 비트 플랫폼에서)로 정렬하여 패딩을 도입하기 때문에 포인터가 같지 않을 것입니다. 이 행동은 표준에 따라 여전히 합법적입니다.

#include <stdio.h>

struct test { char arr[10]; int i; };

int main() {
    struct test t;
    int *p, *q;
    p = (int*)(t.arr + 10);
    q = &t.i;
    if(p == q)
      printf("Equal pointers.");
    else
      printf("Unequal pointers.");
    return 0;
}