2 차원 배열을 할당하는 이상한 방법?
프로젝트에서 누군가 가이 라인을 밀었습니다.
double (*e)[n+1] = malloc((n+1) * sizeof(*e));
아마도 (n + 1) * (n + 1) 배가의 2 차원 배열을 만듭니다.
아마도 지금까지 내가 요청한 사람은 이것이 무엇을, 정확히, 어디서 시작했는지 또는 왜 작동 해야하는지 (어쩌면 그것이 작동하지만 아직 구입하지는 않았는지) 말할 수 없기 때문입니다.
아마도 나는 명백한 것을 놓치고 있지만 누군가 누군가 나에게 위의 줄을 설명 할 수 있다면 고맙게 생각합니다. 개인적으로, 실제로 이해하는 것을 사용하면 훨씬 나아질 것입니다.
변수 e
는 n + 1
유형 의 요소 배열에 대한 포인터 double
입니다.
역 참조 연산자를 e
사용하면 기본 유형 인 e
" n + 1
요소 배열 double
"이 제공됩니다.
이 malloc
호출은 단순히 기본 유형 e
(위에서 설명)을 가져 와서 크기를 가져 와서 곱한 다음 n + 1
해당 크기를 malloc
함수에 전달합니다 . n + 1
의 n + 1
요소 배열을 기본적으로 할당합니다 double
.
이것이 2D 배열을 동적으로 할당해야하는 일반적인 방법입니다.
e
형식의 배열에 대한 배열 포인터double [n+1]
입니다.sizeof(*e)
따라서 지정된 유형의 유형을 제공합니다.이 유형은 한double [n+1]
배열 의 크기입니다 .n+1
그러한 배열을 위한 공간을 할당 합니다.e
이 배열 배열에서 첫 번째 배열을 가리 키 도록 배열 포인터 를 설정합니다 .- 이를 통해
e
as 를 사용e[i][j]
하여 2D 배열의 개별 항목에 액세스 할 수 있습니다.
개인적으로 나는이 스타일이 훨씬 읽기 쉽다고 생각합니다 :
double (*e)[n+1] = malloc( sizeof(double[n+1][n+1]) );
이 관용구는 자연스럽게 1D 배열 할당에서 제외됩니다. 임의의 유형의 1D 배열을 할당하는 것으로 시작합시다 T
.
T *p = malloc( sizeof *p * N );
간단 하죠? 이 표현식 *p
에는 유형 T
이 있으므로 sizeof *p
와 동일한 결과를 제공 sizeof (T)
하므로- N
요소 배열에 충분한 공간을 할당 T
합니다. 이것은 모든 유형T
에 해당됩니다 .
이제 T
와 같은 배열 유형으로 대체합시다 R [10]
. 그러면 우리의 할당은
R (*p)[10] = malloc( sizeof *p * N);
여기서 의미 는 1D 할당 방법 과 정확히 동일 합니다. 변경된 것은의 유형입니다 p
. 대신에 T *
, 지금 R (*)[10]
입니다. 식은 *p
형 갖는 T
타입 R [10]
이므로 sizeof *p
동등 sizeof (T)
동등하다 sizeof (R [10])
. 따라서 N
by by 10
element 배열에 충분한 공간을 할당 하고 R
있습니다.
우리가 원한다면 우리는 이것을 훨씬 더 취할 수 있습니다. R
그 자체가 배열 유형 이라고 가정 합니다 int [5]
. 그것을 대신 R
하고 우리는 얻는다
int (*p)[10][5] = malloc( sizeof *p * N);
같은 거래- sizeof *p
와 동일하며 sizeof (int [10][5])
, N
by 10
by 5
배열 을 보유 할만큼 큰 연속 메모리 덩어리를 할당합니다 int
.
이것이 할당 측면입니다. 액세스 쪽은 어떻습니까?
기억 []
첨자 동작되는 정의 포인터 연산의 관점에서 : a[i]
으로 정의 *(a + i)
1 . 따라서 첨자 연산자 는 포인터를 []
암시 적으로 역 참조합니다. p
에 대한 포인터 인 경우 T
단항 *
연산자를 사용하여 명시 적으로 역 참조하여 지정된 값에 액세스 할 수 있습니다 .
T x = *p;
또는[]
아래 첨자 연산자 를 사용하여 :
T x = p[0]; // identical to *p
따라서 배열p
의 첫 번째 요소를 가리키는 경우 포인터의 아래 첨자를 사용하여 해당 배열의 모든 요소에 액세스 할 수 있습니다 .p
T arr[N];
T *p = arr; // expression arr "decays" from type T [N] to T *
...
T x = p[i]; // access the i'th element of arr through pointer p
이제 대체 작업을 다시 수행하고 T
배열 유형으로 바꾸겠습니다 R [10]
.
R arr[N][10];
R (*p)[10] = arr; // expression arr "decays" from type R [N][10] to R (*)[10]
...
R x = (*p)[i];
하나의 명백한 차이; p
아래 첨자 연산자를 적용하기 전에 명시 적으로 역 참조 하고 있습니다. 우리는에 첨자를 원하지 않고 (이 경우 배열 )을 가리키는 것을p
첨자하고 싶습니다 . 단항 은 첨자 연산자 보다 우선 순위가 낮 으므로 괄호를 사용하여 와 명시 적으로 그룹화 해야 합니다. 하지만 그 이상에서 기억 과 동일 우리가 그것을 대체 할 수 있도록,p
arr[0]
*
[]
p
*
*p
p[0]
R x = (p[0])[i];
아니면 그냥
R x = p[0][i];
따라서 p
2D 배열을 가리키는 경우 p
다음과 같이 통해 해당 배열로 색인을 생성 할 수 있습니다 .
R x = p[i][j]; // access the i'th element of arr through pointer p;
// each arr[i] is a 10-element array of R
상기 및 치환과 같은 결론이 촬영 R
으로 int [5]
:
int arr[N][10][5];
int (*p)[10][5]; // expression arr "decays" from type int [N][5][10] to int (*)[10][5]
...
int x = p[i][j][k];
This works just the same if p
points to a regular array, or if it points to memory allocated through malloc
.
This idiom has the following benefits:
- It's simple - just one line of code, as opposed to the piecemeal allocation method
T **arr = malloc( sizeof *arr * N ); if ( arr ) { for ( size_t i = 0; i < N; i++ ) { arr[i] = malloc( sizeof *arr[i] * M ); } }
- All the rows of the allocated array are *contiguous*, which is not the case with the piecemeal allocation method above;
- Deallocating the array is just as easy with a single call to
free
. Again, not true with the piecemeal allocation method, where you have to deallocate eacharr[i]
before you can deallocatearr
.
Sometimes the piecemeal allocation method is preferable, such as when your heap is badly fragmented and you can't allocate your memory as a contiguous chunk, or you want to allocate a "jagged" array where each row can have a different length. But in general, this is the better way to go.
1. Remember that arrays are not pointers - instead, array expressions are converted to pointer expressions as necessary.
참고URL : https://stackoverflow.com/questions/36794202/freaky-way-of-allocating-two-dimensional-array
'IT story' 카테고리의 다른 글
버퍼 변경을 표시하지 않고 Vim에서 발생 횟수 계산 (0) | 2020.08.02 |
---|---|
백그라운드 프로세스의 종료 코드 가져 오기 (0) | 2020.08.02 |
사제 및 술통 전용 종속성 이해 (0) | 2020.08.02 |
다른 js 파일에서 자바 스크립트 함수 호출 (0) | 2020.08.02 |
내장 파이썬 함수의 소스 코드를 찾으십니까? (0) | 2020.08.02 |