programing

C 또는 C++가 어레이 < 어레이 + SIZE>를 보증하는가?

prostudy 2022. 4. 21. 21:55
반응형

C 또는 C++가 어레이 < 어레이 + SIZE>를 보증하는가?

배열이 있다고 가정해 보십시오.

int array[SIZE];

또는

int *array = new(int[SIZE]);

C 또는 C++는 다음을 보장하는가?array < array + SIZE, 그리고 만약 그렇다면 어디에?

나는 언어 규격과 상관없이 많은 운영체제가 커널을 위해 가상 주소 공간의 상단을 예약함으로써 이 속성을 보증한다는 것을 이해한다.내 질문은 이것 또한 대다수의 구현에 의해서가 아니라 언어에 의해서도 보장되는 것인가 하는 것이다.

예를 들어 OS 커널이 낮은 메모리에 살고 경우에 따라 가장 높은 페이지의 가상 메모리를 사용자 프로세스에 제공한다고 가정해 보십시오.mmap익명 메모리 요청만약malloc또는::operator new[]mmap거대한 어레이의 할당을 위해, 그리고 어레이의 끝은 다음과 같이 가상 주소 공간의 맨 위에 있다.array + SIZE0으로 감싸고 있는데, 이것이 그 언어의 비준수 이행에 해당하는가?

설명

질문이 에 대해 묻는 것이 아니라는 점에 유의하십시오.array+(SIZE-1)인 마마지의 주소 입니다저것보다 더 큰 것이 보장되어 있다.array문제는 배열의 끝에서 1을 지나 포인터에 관한 것이다.p+1할 때p비배열 객체에 대한 포인터(선택한 답변으로 가리킨 표준의 섹션도 동일한 방식으로 취급됨)이다.

Stackoverflow는 나에게 왜 이 질문이 이것과 같지 않은지 설명해 달라고 부탁했다.다른 질문은 포인터의 전체 순서를 어떻게 이행할 것인가를 질문한다.그 다른 질문은 본질적으로 도서관이 어떻게 구현을 할 수 있는가 하는 것이다.std::less다른 할당된 객체에 대한 포인터에도 작동하도록 하는 것. 이 포인터는 표준에 따르면 더 크지도 않고 더 작지도 않은 평등에 대해서만 비교할 수 있다고 한다.

이와는 대조적으로, 제 질문은 배열의 끝을 지나도 배열보다 더 큰 것이 항상 보장되는가에 관한 것이었습니다.내 질문에 대한 대답이 예스인지 아니오인지는 실제로 구현 방법을 바꾸지는 않는다.std::less그래서 다른 질문은 관련이 없어 보인다.배열 끝의 하나와 비교하는 것이 불법이라면,std::less이 경우 단순히 정의되지 않은 행동을 보일 수 있다.(또한, 일반적으로 표준 라이브러리는 컴파일러와 동일한 사람에 의해 구현되므로, 특정 컴파일러의 속성을 자유롭게 이용할 수 있다.)

Yes. From section 6.5.8 para 5.

If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P.

표현arrayp이다. 그 표현은array + SIZE - 1의 마지막 요소를 가리키다array, 즉 Q.따라서 다음과 같다.

array + SIZE = array + SIZE - 1 + 1 = Q + 1 > P = array

C requires this. Section 6.5.8 para 5 says:

pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values

I'm sure there's something analogous in the C++ specification.

This requirement effectively prevents allocating objects that wrap around the address space on common hardware, because it would be impractical to implement all the bookkeeping necessary to implement the relational operator efficiently.

보증서가 그 사건에 대해 유효하지 않다.int *array = new(int[SIZE]);할 때SIZE0이다.

의 결과new int[0]유효한 포인터가 필요하며0여기에 추가되었지만,array == array + SIZE이 경우에, 그리고 엄격히 말해서 테스트보다 덜한 결과가 될 것이다.false.

This is defined in C++, from 7.6.6.4 (p139 of current C++23 draft):

When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.

(4.1) — If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.

(4.2) — Otherwise, if P points to an array element i of an array object x with n elements (9.3.4.5) the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) array element i + j of x if 0 <= i + j <= n and the expression P - J points to the (possibly-hypothetical) array element i − j of x if 0 <= i − j <= n.

(4.3) — Otherwise, the behavior is undefined.

Note that 4.2 explicitly has "<= n", not "< n". It's undefined for any value larger than size(), but is defined for size().

The ordering of array elements is defined in 7.6.9 (p141):

(4.1) If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript is required to compare greater.

즉, 잘 정의된 n > 0의 모든 사례에 대해 가상 요소 n이 배열 자체(원소 0)보다 더 큰 비교를 할 것이라는 뜻이다.

C++의 관련 규칙은 [expr.rel]/4.1:

두 포인터가 동일한 배열의 다른 요소 또는 그 하위 객체를 가리키는 경우, 더 큰 비교를 위해 더 높은 첨자를 가진 요소에 대한 포인터가 필요하다.

위의 규칙은 배열 요소에 대한 포인터만 포함하는 것으로 나타나며,array + SIZE배열 요소를 가리키지 않는다.그러나 각주에 언급된 바와 같이 여기서 원 패스 더 엔드 포인터는 배열 요소인 것처럼 취급된다.관련 언어 규칙은 [basic.compound]/3:

포인터 산술([expr.add]) 및 비교([expr.rel]), 포인터(xpr.eq])의 경우 배열의 마지막 요소 끝을 통과한다.xn 요소의 경우, n의 가상 배열 요소에 대한 포인터와 동등한 것으로 간주된다.x그리고 타입의 물건T즉, 배열 요소가 아닌 요소가 하나의 유형 요소를 가진 배열로 간주됨T.

그래서 C++는 그것을 보증한다.array + SIZE > array(적어도 그럴 때는)SIZE > 0)) 그리고 저것&x + 1 > &x어떤 목적으로든x.

어레이는 내부에 연속적인 메모리 공간이 보장된다. c++03 이후 벡터에도 연속적인 메모리 공간이 보장된다.&vec[0] ... &vec[vec.size() - 1]. 이것은 자동적으로 당신이 묻고 있는 것이 사실이라는 것을 의미한다.
그것은 연속 저장이라고 불린다. 벡터들을 위해 여기서 찾을 수 있다.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0944r0.html

벡터의 요소는 연속적으로 저장되는데, 즉, v가 벡터<T, Assignator>인 경우 T가 bool이 아닌 다른 유형이라면, 0 <=n <= v.size() 모두에 대해 &v[n] = &v[0] + n을 준수한다는 뜻이다.추정컨대 캐싱과 근위성의 상호작용을 5년 더 연구한 결과, WG21은 근위성이 요구되어야 하고 비연속 벡터 구현이 명확하게 금지되어야 한다는 것을 명확히 했다.

후자는 표준 문서로부터 왔다.C++03 내가 맞혔어.

참조URL: https://stackoverflow.com/questions/66434355/does-c-or-c-guarantee-array-array-size

반응형