배열의 최대 크기가 "너무 큰"이유는 무엇입니까?
나는 같은 인상을 해요이 대답 , size_t
주어진 시스템의 가장 큰 가능한 유형을 보유 할 충분한 표준에 의해 보장된다.
그러나이 코드는 gcc / Mingw에서 검증되지 않습니다.
#include <stdint.h>
#include <stddef.h>
typedef uint8_t array_t [SIZE_MAX];
오류 : 배열 'array_t'의 크기가 너무 섭섭니다.
여기 표준에서 뭔가 오해하고 있습니까? 주어진 size_t
구현을 위해 너무 클 수? 아니면 Mingw의 또 다른 버그입니까?
편집 : 추가 연구에 따르면
typedef uint8_t array_t [SIZE_MAX/2]; // does compile
typedef uint8_t array_t [SIZE_MAX/2+1]; // does not compile
다음과 같은 일이 발생합니다.
#include <limits.h>
typedef uint8_t array_t [LLONG_MAX]; // does compile
typedef uint8_t array_t [LLONG_MAX+(size_t)1]; // does not compile
그래서 저는 이제 이것이 Mingw의 버그라고 믿고 있습니다. 부호있는 정수 유형을 기반으로 최대 허용 크기를 설정하는 것은 의미가 있기 때문입니다.
제한 SIZE_MAX / 2는 ptrdiff_t 및 size_t 유형이 너비를 갖도록 선택하는 구현의 size_t 및 ptrdiff_t 정의에서 비롯됩니다.
C 표준 은 size_t 유형이 서명되지 않고 ptrdiff_t 유형이 서명 1 을 요구 합니다.
두 포인터 값 차이의 결과는 항상 2 가 ptrdiff_t 유형을 갖습니다. 즉, 구현시 개체의 크기를 PTRDIFF_MAX로 제한해야합니다. 일치하지 않는 두 포인터의 유효한 차이를 ptrdiff_t 형식으로 표현할 수 없어 정의되지 않은 동작이 발생합니다.
따라서 SIZE_MAX / 2 값은 PTRDIFF_MAX 값과 가변적입니다. 구현에서 최대 크기를 SIZE_MAX로 선택하면 ptrdiff_t 유형의 너비를 늘려야합니다. 그러나 클래스의 최대 크기를 SIZE_MAX / 2로 제한하는 것이 훨씬 더 있습니다. 그러면 ptrdiff_t 유형이 size_t 유형보다 크거나 같은 양의 범위를 갖도록하는 것이 부담 스럽습니다.
Standard는 주제 에 대한 3 개의 댓글 4가 제공 됩니다.
(ISO / IEC 9899 : 201x에서 인용)
1 (7.19 공통 정의 2)
유형은 두 포인터를 뺀 결과의 부호있는 정수 유형 인
ptrdiff_t
입니다. sizeof 연산자 결과의 부호없는 정수 유형 인
size_t
;
2 (6.5.6 덧셈 연산자 9)
두 포인터를 빼면 둘 다 배열 배열의 요소를 가리켜 야하거나 배열의 마지막 요소를 지나는 하나를 가리켜 야합니다. 결과는 두 배열 요소의 첨자의 차이입니다. 결과의 크기는 구현에 따라 정의 된 해당 유형 (부호있는 정수 유형)은 헤더에 정의 된 ptrdiff_t입니다. 결과가 해당 유형의 객체에서 표현할 수없는 경우 동작은 정의되지 않습니다.
3 (K.3.4 정수 유형 3)
매우 큰 개체 크기는 개체 크기가 잘못 계산되는 것은 신호입니다. 예를 들어 음수는 size_t와 같은 부호없는 유형으로 변환 될 때 매우 큰 양수로 나타납니다. 또한 일부 구현은 size_t 유형으로 표현할 수있는 최대 값만큼 큰 수업을 지원하지 않습니다.
4 (K.3.4 정수 유형 4)
그래야만 프로그래밍 오류를 감지하기 위해 클래스 크기 범위를 제한하는 것이 유익합니다. 주소 공간이 큰 머신을 대상으로하는 구현의 경우, RSIZE_MAX는 지원되는 가장 큰 개체의 크기 또는 (SIZE_MAX >> 1)보다 작은 것이 정의하는 것이 좋습니다.이 제한이 일부 합법적 인 크기보다 작지만 매우 물건입니다. 컴퓨터를 대상으로하는 작은 주소 공간을 가진 구현에서는 RSIZE_MAX를 SIZE_MAX로 정의 할 수 있습니다. 즉, 알림이 제공되는 개체 크기가 없음을 의미합니다.
범위의 범위 size_t
는 구현에서 지원하는 가장 큰 개체의 크기를 저장하기에 충분합니다. 그 반대는 사실이 아닙니다. 크기가의 전체 범위를 채우는 개체를 만들 수 있다는 보장은 없습니다 size_t
.
이러한 상황에서 질문은 무엇 SIZE_MAX
을 의미합니까? 지원되는 가장 큰 개체 크기는 무엇입니까? 또는 size_t
? 대답은 후자 SIZE_MAX
입니다 (size_t) -1
. 즉 . SIZE_MAX
큰 개체를 만들 수 있다는 보장은 없습니다 .
그 뒤에있는 이유는 size_t
구현시를 제공해야하기 때문입니다 ptrdiff_t
. 이는 동일한 배열 객체를 가리키는 두 포인터 간의 차이를 저장하도록 의도되었지만 보장되지는 않습니다. 유형 ptrdiff_t
이 서명되었으므로 구현에는 다음 선택 사항이 있습니다.
크기의 어레이 객체를 허용
SIZE_MAX
하고하게ptrdiff_t
넓어 보다size_t
. 적어도 1 비트 더 넓어야합니다. 이러한ptrdiff_t
크기의 배열을 가리키는 두 개의 포인터의 차이 대응할 수SIZE_MAX
이하인.크기의 어레이 오브젝트 허용
SIZE_MAX
및 사용ptrdiff_t
의 동일한 폭 등을size_t
. 포인터가 요소 보다 멀리 떨어져 있으면 포인터 빼기가 오버플로 되어 정의되지 않은 동작을 유발할 수 있다는 사실을 받아들SIZE_MAX / 2
입니다. 언어 사양은이 접근 방식을 금지하지 않습니다.사용
ptrdiff_t
과 같은 폭size_t
과 제한 에 의한 최대 배열 객체의 크기를SIZE_MAX / 2
. 이러한ptrdiff_t
크기의 배열을 가리키는 두 개의 포인터의 차이 대응할 수SIZE_MAX / 2
이하인.
세 번째 접근 방식을 따르기로 결정한 구현을 단순히 다루고 있습니다.
구현 별 동작과 매우 유사합니다.
저는 여기서 Mac OS를 실행하고 있으며 gcc 6.3.0에서 정의를 컴파일 할 수있는 가장 큰 크기는 다음과 같습니다 SIZE_MAX/2
. 와 SIZE_MAX/2 + 1
그것을 더 이상 컴파일되지 않습니다.
반면에 마녀 clang 4.0.0이 가장 큰 것은 SIZE_MAX/8
이며 SIZE_MAX/8 + 1
중단됩니다.
처음부터 추론하는 것만 size_t
으로 어떤 물체의 크기도 담을 수있는 유형입니다. 객체의 크기는 주소 버스의 너비에 의해 제한됩니다 (예를 들어 32 비트 및 64 비트 코드를 처리 할 수있는 멀티플렉싱 및 시스템을 무시하고 "코드 너비"라고 함). MAX_INT
가장 큰 정수 값인 Anologous SIZE_MAX
는의 가장 큰 값입니다 size_t
. 따라서 크기의 개체 SIZE_MAX
는 모두 주소 지정이 가능한 메모리입니다. 구현시 오류로 플래그를 지정하는 것이 합리적이지만 스택 또는 전역 메모리에있는 실제 개체가 할당 된 경우에만 오류라는 데 동의합니다. ( malloc
어쨌든 그 금액 에 대한 호출 은 실패합니다)
참조 URL : https://stackoverflow.com/questions/42574890/why-is-the-maximum-size-of-an-array-too-large
'ProgramingTip' 카테고리의 다른 글
부모 RecyclerView 안에있는 방법은 무엇입니까? (0) | 2021.01.07 |
---|---|
getCurrentPosition () 및 watchPosition ()은 안전하지 않은 출처에서 더 이상 사용되지 않습니다. (0) | 2021.01.07 |
AngularJS에서. $ on ()은 무엇입니까? (0) | 2021.01.06 |
TypeError : data.push는 함수가 아닙니다. (0) | 2021.01.06 |
Ansible set_fact를 사용하여 예측 결과에서 사전 생성 (0) | 2021.01.06 |